用途:在 Flutter 项目的 Presentation 层按 MVI 风格组织画面代码,让状态、行为与 UI 分离,便于测试与预览。
主要能力与结构:每个画面由 State、Action、ViewModel、Root/Screen 四部分组成,只创建 2 个文件——<feature>_view_model.dart(上为 State、Action,下为 ViewModel)与 <feature>_screen.dart(上为 Root,下为 Screen)。State 为 freezed 不可变类,默认值用 @Default;Action 为 freezed sealed class,用 switch 强制覆盖所有分支,命名如 onTapFavorite 或 loadRecipe。ViewModel 用 with ChangeNotifier 混入,仅暴露单一 onAction(Action) 入口做 switch 分发,状态更新固定先 copyWith 再 notifyListeners,依赖只走构造注入,不在内部调用 getIt。Root 负责 getIt 取 ViewModel、事件订阅与 ListenableBuilder 观察;Screen 只接收 state 与 onAction,保持纯 UI。
一次性事件:Snackbar、导航等副作用用 StreamController 输出,在 Root 的 initState 中 listen 处理,避免放进 State 导致重复触发。
使用方式:新增画面时创建上述两文件,在 diSetup() 中以 registerFactory 注册 ViewModel,必要时用 StreamController 暴露一次性事件,并运行 build_runner build 生成 freezed 文件。导航等需要 context 的交互用额外 onTap* 回调交给 Root,ViewModel 不引用 BuildContext 或 GoRouter。
限制与注意:资料提醒 build 内调用 load Action 是本项目既有惯例,但需防止重建重复加载,复杂初始化建议提升为 StatefulWidget 的 initState;StreamSubscription 必须在 dispose 中 cancel;避免 Screen 直接调用 getIt、ViewModel 暴露多个公开方法、改状态后漏掉 notifyListeners;本页未提供安装命令、许可证与价格等信息。