# Gerenciando estado

> Sem binding reativo — estado em campos/ViewModel, a View traduz estado→componentes na mão.

Source: https://crossfly.dev/pt/docs/learn/managing-state — CrossFly documentation. Full docs as one file: https://crossfly.dev/llms-full.txt

# 7. Gerenciando estado

> **O que você vai aprender:** o modelo de estado do CrossFly — onde quem vem de Flutter/React precisa
> **desaprender**. **Pré-requisitos:** [Lidando com entrada](/docs/learn/handling-input).

## Exemplo completo (copiar, colar e rodar)
Uma ViewModel leve (`TarefaVM`) com `observe(Runnable)` manual (não há binding reativo): a View re-popula
os componentes quando o estado muda. Um botão adiciona tarefas e a lista se re-renderiza. Compila como está.
```java
package com.exemplo;

import java.util.*;
import dev.crossfly.ui.*;
import dev.crossfly.ui.layout.*;

public class MainWindow extends Window
{
   private final TarefaVM vm = new TarefaVM();
   private final Component listaBox = new Component();
   private int contador = 1;

   @Override
   public void onShow() throws Exception
   {
      super.onShow();
      setLayout(new VerticalLayout());

      Button add = new Button("Adicionar tarefa");
      add.onAction(c -> vm.adicionar(new Tarefa("Tarefa " + (contador++))));
      add(LAY_AUTO, add);

      listaBox.setLayout(new VerticalLayout());
      add(LAY_FILL, listaBox);

      vm.observe(this::renderizarLista);   // re-popula quando o estado muda
      renderizarLista();
   }

   private void renderizarLista()
   {
      listaBox.removeAll();
      for (Tarefa t : vm.tarefas) listaBox.add(LAY_AUTO, new Label(t.titulo));
      listaBox.setValidLayout(false);      // o tamanho mudou
      Component.repaint();
   }
}

class Tarefa
{
   final String titulo;
   Tarefa(String titulo) { this.titulo = titulo; }
}

class TarefaVM
{
   private Runnable onChange;
   public List<Tarefa> tarefas = new ArrayList<>();

   public void observe(Runnable r) { this.onChange = r; }
   private void mudou() { if (onChange != null) onChange.run(); }

   public void adicionar(Tarefa t)
   {
      var novo = new ArrayList<>(tarefas); novo.add(t);
      tarefas = novo;
      mudou();                             // notifica a View (na paint thread)
   }
}
```
> Os trechos abaixo mostram **só o miolo** (o que vai dentro de `onShow()`). Para rodar, coloque-os no esqueleto `MainWindow` acima.

## Não há binding reativo
Mudar o modelo **não** atualiza a UI sozinho. O estado vive em campos (ou numa **ViewModel** leve), e a
View **traduz estado → componentes manualmente**, chamando `repaint()` (e `setValidLayout(false)` se o
tamanho mudou).

## Uma ViewModel leve com `observe`
```java
public class TarefaVM {
   private Runnable onChange;
   public List<Tarefa> tarefas = List.of();
   public void observe(Runnable r) { this.onChange = r; }
   private void mudou() { if (onChange != null) onChange.run(); }

   public void adicionar(Tarefa t) {
      var novo = new ArrayList<>(tarefas); novo.add(t);
      tarefas = novo;
      mudou();                    // notifica a View (na paint thread)
   }
}
```

## A View reage
```java
@Override public void onShow() throws Exception {
   super.onShow();
   // … monta UI …
   vm.observe(this::renderizarLista);   // re-popula os componentes quando o estado muda
   vm.carregar();                       // dispara o carregamento (em background — próximo capítulo)
}

private void renderizarLista() {
   listaBox.removeAll();
   for (Tarefa t : vm.tarefas) { CardTarefa card = new CardTarefa(); listaBox.add(LAY_AUTO, card); card.bind(t); }
   listaBox.setValidLayout(false);
   Component.repaint();
}
```
> Regra: mutações e notificações **sempre na paint thread**. Se o dado veio de fundo, entre em
> `Component.onUI(...)` antes de mexer no estado que a View lê (ver próximo capítulo).

## Constrói neste passo
A **`TarefaVM`** com a tela se re-renderizando quando o estado muda.

## Recapitulando
Sem reativo: estado em campos/ViewModel; a View traduz estado→componentes com `repaint()`; um
`observe(Runnable)` manual substitui o binding.

## Próximos passos
→ [Carregando dados](/docs/learn/loading-data)

## Veja também
- Conceito: [Estado e fluxo de dados](/docs/concepts/state-and-data-flow) · [Arquitetura de app](/docs/best-practices/arquitetura-de-app)
