This page was machine-translated from Portuguese and may contain errors. The Portuguese version is canonical.
State and data flow
This is where CrossFly most surprises those coming from Flutter, Compose, SwiftUI, or React. Two deliberate absences:
- There is no automatic reactive binding. No
setState, observables,@State, or recomposition. Changing the model does not update the UI on its own. - There is no dependency injection container. No Dagger/Guice/Spring. You build and pass your dependencies by hand (typically through the screen’s constructor).
The model: imperative + explicit invalidation
You read/write the model, update the component directly, and the framework repaints:
model.nome = "Ana";
label.setText(model.nome); // most setters already invalidate the layout and call repaint()
Most component setters already fire repaint()/invalidate the layout for you. The single
rule to remember:
Changed state the framework doesn’t know about (a counter of yours, a computation, a field drawn in
onPaint)? You callrepaint(). (See The paint thread.)
The classic counterexample
this.progresso = 0.7f; // I changed a field that only my onPaint reads…
// …and the screen doesn't change. Missing:
Component.repaint(); // ✔ now the next frame reflects the new value
“I changed the state and the screen didn’t update” is, almost always, a missing repaint().
Why this choice
- Predictability: the flow is linear and visible — data → setter → repaint → frame. There is no magic recomposition nor hidden reactive cycle to debug.
- Zero magic, low cost: no reactive dependency graph, no DI framework to configure.
- The price is explicitness: managing state is the application’s responsibility, not the framework’s.
The communication mechanisms the framework offers
- Callbacks / actions —
onAction(...), callbacks passed through the constructor (see Returning results). - Parent/child hierarchy — navigate the component tree.
property(k, v)— the per-component “data bag” (see Everything is a Component).- Global state — static fields/shared services when it makes sense.
The recommended pattern
Since the framework only provides the building blocks, the organization pattern (a ViewModel/controller
per screen + repository for data) is an application convention — documented in
best-practices. The framework does not impose an architecture; it offers
components and the setter→repaint() pair.