You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter MVVM架构下如何无需重建等操作更新整个ViewModel数据

实现无需手动重建的Flutter MVVM ViewModel监听方案

核心思路

通过Flutter原生的ChangeNotifier实现ViewModel的变化通知,结合自定义InheritedNotifier(继承自InheritedWidget)让Widget自动感知ViewModel的整体变化,完全满足你的需求:无需手动调用重建方法、不用Stream/Future Builder、无外部依赖。


步骤1:让ViewModel继承ChangeNotifier

给ViewModel添加变化通知能力,当ViewModel整体数据更新时调用notifyListeners()触发更新:

class MyViewModel extends ChangeNotifier {
  // 示例业务数据
  String _pageTitle = "初始页面标题";
  int _dataCount = 0;

  // 暴露只读 getter
  String get pageTitle => _pageTitle;
  int get dataCount => _dataCount;

  // 更新ViewModel整体数据的方法(根据业务需求自定义)
  void refreshViewModel(String newTitle, int newCount) {
    _pageTitle = newTitle;
    _dataCount = newCount;
    // 通知所有依赖的Widget自动更新
    notifyListeners();
  }
}

步骤2:自定义ViewModelProvider(基于InheritedNotifier)

封装一个继承自InheritedNotifier的Provider类,用于在Widget树中传递ViewModel,并自动监听其变化:

class ViewModelProvider<T extends ChangeNotifier> extends InheritedNotifier<T> {
  final T viewModel;

  const ViewModelProvider({
    super.key,
    required this.viewModel,
    required super.child,
  }) : super(notifier: viewModel);

  // 静态工具方法,方便子Widget快速获取ViewModel
  static T? of<T extends ChangeNotifier>(BuildContext context) {
    return context.dependOnInheritedWidgetOfExactType<ViewModelProvider<T>>()?.viewModel;
  }
}

步骤3:在Widget中使用ViewModel

子Widget通过ViewModelProvider.of()获取ViewModel,当ViewModel调用notifyListeners()时,该Widget会自动重建,无需手动触发:

class HomeView extends StatelessWidget {
  const HomeView({super.key});

  @override
  Widget build(BuildContext context) {
    // 获取ViewModel,自动建立依赖关系
    final viewModel = ViewModelProvider.of<MyViewModel>(context)!;

    return Scaffold(
      appBar: AppBar(title: Text(viewModel.pageTitle)),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Text("当前计数: ${viewModel.dataCount}", style: const TextStyle(fontSize: 20)),
            const SizedBox(height: 20),
            ElevatedButton(
              onPressed: () {
                // 更新ViewModel数据,无需手动调用setState或rebuild
                viewModel.refreshViewModel("更新后的标题", viewModel.dataCount + 1);
              },
              child: const Text("更新数据"),
            ),
          ],
        ),
      ),
    );
  }
}

步骤4:在顶层注入ViewModel

在应用入口处将ViewModel注入到Widget树中:

void main() {
  runApp(
    ViewModelProvider(
      viewModel: MyViewModel(),
      child: const MaterialApp(
        home: HomeView(),
      ),
    ),
  );
}

为什么之前的InheritedWidget没生效?

多数情况是因为你没有将InheritedWidget和变化监听机制结合:普通的InheritedWidget只会在自身updateShouldNotify返回true时触发更新,而结合ChangeNotifier和InheritedNotifier后,ViewModel的变化会自动触发InheritedWidget的更新通知,无需手动实现updateShouldNotify逻辑。

内容的提问来源于stack exchange,提问作者Rafaelo Vandov

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.01 15:35:50