Skip to content
CrossFly is 100% open sourceFollow us on GitHub
CrossFlyCrossFly
Get started

This page was machine-translated from Portuguese and may contain errors. The Portuguese version is canonical.

State management

If you come from React/Flutter/Compose, brace yourself for the biggest difference: there is no reactive data-binding. No useState/Observable/setState() that redraws on its own. The model is imperative + explicit invalidation — the “why” is in State and data flow.

The pattern

State lives in plain fields of an object of yours (a ViewModel/service). When it changes, you update the widget and call repaint() — if it came from another thread, inside Component.onUI(...).

class HomeVM {
   List<Cliente> clientes = new ArrayList<>();
}

public class TelaHome extends Window {
   private final HomeVM vm = new HomeVM();
   private ListView<Cliente> lista;

   @Override public void onShow() throws Exception {
      super.onShow();
      setLayout(new VerticalLayout());
      add(LAY_FILL, lista = new ListView<>());
      carregar();
   }

   private void carregar() {
      new Thread(() -> {
         List<Cliente> dados = repositorio.buscarTudo();   // heavy work, background thread
         Component.onUI(() -> {                             // back to the paint thread
            vm.clientes = dados;
            lista.setItems(dados);                          // updates the widget
            Component.repaint();                            // requests a new frame
         });
      }).start();
   }
}

Ephemeral vs. application state

Type Where it lives Survives navigation?
ephemeral (screen) Window fields no — gone when you leave the screen
application a shared singleton/service yes — persists across screens

Choose by scope: a search filter is ephemeral; the logged-in user is application state.

Best practices

  • One ViewModel per screen concentrates state and logic; the Window only wires UI ↔ VM.
  • State shared across screens → service/singleton, not scattered static fields.
  • Always return to the UI with onUI(...) before touching widgets from a background thread.

Common mistakes

  • Expecting that changing the model updates the UI on its own — it does not; call setX(...) + repaint().
  • Storing app state in Window fields (lost when you navigate).

See also

Was this page helpful?