Saltar al contenido
CrossFly es 100% open sourceSíguenos en GitHub
CrossFlyCrossFly
Empezar

Esta página fue traducida automáticamente del portugués y puede contener errores. La versión en portugués es la canónica.

7. Gestionando el estado

Lo que vas a aprender: el modelo de estado de CrossFly — donde quien viene de Flutter/React necesita desaprender. Prerrequisitos: Manejando la entrada.

Ejemplo completo (copiar, pegar y ejecutar)

Una ViewModel liviana (TarefaVM) con observe(Runnable) manual (no hay binding reactivo): la View re-puebla los componentes cuando el estado cambia. Un botón agrega tareas y la lista se re-renderiza. Compila tal cual.

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-puebla cuando el estado cambia
      renderizarLista();
   }

   private void renderizarLista()
   {
      listaBox.removeAll();
      for (Tarefa t : vm.tarefas) listaBox.add(LAY_AUTO, new Label(t.titulo));
      listaBox.setValidLayout(false);      // el tamaño cambió
      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 la View (en el paint thread)
   }
}

Los fragmentos de abajo muestran solo el núcleo (lo que va dentro de onShow()). Para ejecutar, colócalos en el esqueleto MainWindow de arriba.

No hay binding reactivo

Cambiar el modelo no actualiza la UI solo. El estado vive en campos (o en una ViewModel liviana), y la View traduce estado → componentes manualmente, llamando a repaint() (y setValidLayout(false) si el tamaño cambió).

Una ViewModel liviana con observe

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 la View (en el paint thread)
   }
}

La View reacciona

@Override public void onShow() throws Exception {
   super.onShow();
   // … monta UI …
   vm.observe(this::renderizarLista);   // re-puebla los componentes cuando el estado cambia
   vm.carregar();                       // dispara la carga (en 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();
}

Regla: las mutaciones y notificaciones siempre en la paint thread. Si el dato vino de fondo, entra en Component.onUI(...) antes de tocar el estado que la View lee (ver próximo capítulo).

Construyes en este paso

La TarefaVM con la pantalla re-renderizándose cuando el estado cambia.

Recapitulando

Sin reactivo: estado en campos/ViewModel; la View traduce estado→componentes con repaint(); un observe(Runnable) manual sustituye el binding.

Próximos pasos

→ Cargando datos

Ver también

¿Te resultó útil esta página?