Flutter中MVC与MVVM架构的区别及正确实现问询
Flutter中MVC与MVVM的核心差异及正确实现方式
很多人会误以为MVC和MVVM只是换个类名,但两者的核心逻辑、数据流向和职责划分完全不同,下面结合你做的用户列表场景拆解清楚:
一、核心差异对比
MVC的核心逻辑
- Controller是「命令执行者」:它直接持有View的引用,既要处理业务逻辑(比如请求用户列表),又要主动触发View更新(比如调用
setState或View的刷新方法)。 - 耦合性高:View和Controller互相依赖,业务逻辑和UI更新代码容易混在一起,后期维护成本高。
MVVM的核心逻辑
- ViewModel是「数据提供者」:它完全不持有View的引用,只负责暴露可观察的状态(比如用
ChangeNotifier、ValueNotifier或Stream),让View自行订阅状态变化。 - 完全解耦:View只负责UI渲染和用户交互,ViewModel只处理业务逻辑和状态管理,两者通过状态绑定关联,没有直接依赖。
二、从MVC到MVVM的具体改造示例
假设你的MVC用户列表代码大致如下,我们一步步改成标准MVVM:
MVC实现示例
// Model class User { final String id; final String name; User(this.id, this.name); } // Controller class UserListController { // 直接持有View引用 UserListView? view; List<User> users = []; Future<void> fetchUsers() async { // 模拟网络请求 await Future.delayed(const Duration(seconds: 1)); users = [User("1", "张三"), User("2", "李四")]; // 主动通知View更新 view?.updateUI(); } } // View class UserListView extends StatefulWidget { @override _UserListViewState createState() => _UserListViewState(); } class _UserListViewState extends State<UserListView> { final controller = UserListController(); @override void initState() { super.initState(); // 将View实例传给Controller controller.view = this; } void updateUI() { setState(() {}); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: const Text("用户列表")), body: ListView.builder( itemCount: controller.users.length, itemBuilder: (context, index) => ListTile(title: Text(controller.users[index].name)), ), floatingActionButton: FloatingActionButton( onPressed: controller.fetchUsers, child: const Icon(Icons.refresh), ), ); } }
改成MVVM的正确方式
核心是移除ViewModel对View的引用,用可观察状态替代手动调用View更新,这里以ChangeNotifier为例:
// Model 可直接复用,无需修改 class User { final String id; final String name; User(this.id, this.name); } // ViewModel class UserListViewModel extends ChangeNotifier { List<User> _users = []; // 对外暴露只读的状态 List<User> get users => _users; Future<void> fetchUsers() async { await Future.delayed(const Duration(seconds: 1)); _users = [User("1", "张三"), User("2", "李四")]; // 通知所有订阅的View更新状态 notifyListeners(); } } // View class UserListView extends StatefulWidget { @override _UserListViewState createState() => _UserListViewState(); } class _UserListViewState extends State<UserListView> { final viewModel = UserListViewModel(); @override Widget build(BuildContext context) { // 用Consumer订阅ViewModel的状态变化,自动触发UI更新 return Scaffold( appBar: AppBar(title: const Text("用户列表")), body: Consumer<UserListViewModel>( builder: (context, vm, child) => ListView.builder( itemCount: vm.users.length, itemBuilder: (context, index) => ListTile(title: Text(vm.users[index].name)), ), ), floatingActionButton: FloatingActionButton( onPressed: viewModel.fetchUsers, child: const Icon(Icons.refresh), ), ); } }
三、关键差异总结
- 职责边界:MVC的Controller既要处理业务逻辑,又要管理View的更新;MVVM的ViewModel只负责状态和业务,View只负责UI渲染。
- 耦合程度:MVC中Controller和View互相依赖,修改一方可能影响另一方;MVVM中两者完全独立,ViewModel可复用给不同View。
- 更新机制:MVC是Controller主动调用View方法更新;MVVM是View订阅状态,自动响应变化。
内容的提问来源于stack exchange,提问作者d3ridi
相关产品推荐
相关产品推荐

