Estado e fluxo de dados
É aqui que o CrossFly mais surpreende quem vem de Flutter, Compose, SwiftUI ou React. Duas ausências deliberadas:
- Não há binding reativo automático. Nada de
setState, observáveis,@Stateou recomposição. Mudar o modelo não atualiza a UI sozinho. - Não há contêiner de injeção de dependência. Nada de Dagger/Guice/Spring. Você constrói e passa suas dependências à mão (tipicamente pelo construtor da tela).
O modelo: imperativo + invalidação explícita
Você lê/escreve o modelo, atualiza o componente diretamente e o framework repinta:
model.nome = "Ana";
label.setText(model.nome); // a maioria dos setters já invalida o layout e chama repaint()
A maior parte dos setters de componente já dispara repaint()/invalida o layout por você. A regra
única a lembrar:
Mudou estado que o framework não conhece (um contador seu, um cálculo, um campo desenhado no
onPaint)? Você chamarepaint(). (Ver A paint thread.)
O contraexemplo clássico
this.progresso = 0.7f; // mudei um campo que só o meu onPaint lê…
// …e a tela não muda. Falta:
Component.repaint(); // ✔ agora o próximo frame reflete o novo valor
“Mudei o estado e a tela não atualizou” é, quase sempre, um repaint() faltando.
Por que essa escolha
- Previsibilidade: o fluxo é linear e visível — dado → setter → repaint → frame. Não há recomposição mágica nem ciclo reativo escondido para depurar.
- Zero mágica, custo baixo: sem grafo de dependências reativo, sem framework de DI para configurar.
- O preço é explicitude: gerenciar estado é responsabilidade da aplicação, não do framework.
Os mecanismos de comunicação que o framework oferece
- Callbacks / actions —
onAction(...), callbacks passados por construtor (ver Retornar valores). - Hierarquia pai/filho — navegar a árvore de componentes.
property(k, v)— o “saco de dados” por componente (ver Tudo é um Component).- Estado global — campos estáticos/serviços compartilhados quando fizer sentido.
O padrão recomendado
Como o framework só dá os blocos, o padrão de organização (um ViewModel/controller por tela +
repositório para dados) é convenção da aplicação — documentado em
best-practices. O framework não impõe arquitetura; ele oferece
componentes e o par setter→repaint().
Veja também
- Relacionado: A paint thread · Arquitetura de app (best-practices)