跳到内容
CrossFly 是 100% 开源在 GitHub 关注我们
CrossFlyCrossFly
开始使用

本页面由葡萄牙语机器翻译,可能存在错误。葡萄牙语版本为准。

7. 管理状态

你将学到: CrossFly 的状态模型 —— 这里是来自 Flutter/React 的人需要忘却重学之处。前置条件: 处理输入。

完整示例(复制、粘贴、运行)

一个轻量的 ViewModel(TarefaVM),带手动的 observe(Runnable)(没有响应式绑定):当状态变化时 View 重新填充组件。一个按钮添加任务,列表随之重新渲染。可直接编译运行。

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);   // 状态变化时重新填充
      renderizarLista();
   }

   private void renderizarLista()
   {
      listaBox.removeAll();
      for (Tarefa t : vm.tarefas) listaBox.add(LAY_AUTO, new Label(t.titulo));
      listaBox.setValidLayout(false);      // 尺寸已改变
      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();                             // 通知 View(在 paint thread 上)
   }
}

下面的片段只展示核心部分(放在 onShow() 里的内容)。要运行,请把它们放进上面的 MainWindow 骨架里。

没有响应式绑定

修改模型不会自动更新 UI。状态存活于字段(或一个轻量的 ViewModel)中,而 View 手动将状态 → 组件翻译,调用 repaint()(如果尺寸变化了,还要调用 setValidLayout(false))。

一个带 observe 的轻量 ViewModel

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();                    // 通知 View(在 paint thread 上)
   }
}

View 做出反应

@Override public void onShow() throws Exception {
   super.onShow();
   // … 构建 UI …
   vm.observe(this::renderizarLista);   // 状态变化时重新填充组件
   vm.carregar();                       // 触发加载(在后台 — 下一章)
}

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();
}

规则:修改和通知始终在绘制线程上进行。如果数据来自后台,在改动 View 读取的状态之前,先进入 Component.onUI(...)(见下一章)。

本步骤所构建的

TarefaVM 以及在状态变化时会重新渲染的界面。

回顾

无响应式:状态存于字段/ViewModel;View 用 repaint() 将状态→组件翻译;一个手动的 observe(Runnable) 替代了绑定。

下一步

→ 加载数据

另见

这个页面有帮助吗?