# Flutter状态管理对比:view_model vs Riverpod

叠甲。本文纯偏向 view_model。Riverpod 更牛逼。

在Flutter状态管理的世界里,开发者经常面临一个困扰:功能强大的方案往往伴随着复杂的学习曲线和冗长的模板代码。今天我们来对比两个状态管理方案:追求极简的 view_model 和功能全面的 Riverpod.

🎯 设计哲学的根本差异

view_model:相信开发者的简洁主义

dart 复制代码
// 定义:干净利落
class UserViewModel extends ViewModel {
  String _name = "";
  String get name => _name;
  
  void updateName(String newName) {
    _name = newName;
    notifyListeners();
  }
}

// 使用:一目了然
class UserViewModelFactory with ViewModelFactory<UserViewModel> {
  @override
  UserViewModel build() => UserViewModel();
  @override
  String? key() => "current-user";
}

// 在Widget中:直接了当
UserViewModel get userVM => watchViewModel(factory: UserViewModelFactory());

Riverpod:面面俱到的工程化方案

dart 复制代码
// 定义:类型参数满天飞
final userProvider = StateNotifierProvider<UserNotifier, UserState>((ref) {
  return UserNotifier();
});

final userWithIdProvider = StateNotifierProvider.family<UserNotifier, UserState, String>((ref, userId) {
  return UserNotifier(userId);
});

// 使用:概念层层包装
class MyWidget extends ConsumerWidget {
  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final userState = ref.watch(userProvider);
    return Text(userState.name);
  }
}

📊 开发体验对比

学习曲线

flutter_view_model

  • ✅ 5分钟上手:ViewModel + Factory + watchViewModel
  • ✅ 概念单一:只需要理解ViewModel和Factory
  • ✅ 错误友好:出错了很容易定位问题

Riverpod

  • ❌ 需要1-2天学习:Provider、Consumer、Ref、Family、AutoDispose...
  • ❌ 概念繁多:StateProvider、StateNotifierProvider、FutureProvider...
  • ❌ 调试复杂:Provider依赖图、生命周期管理

代码简洁度

创建一个带参数的状态管理

flutter_view_model:

dart 复制代码
class TodoListFactory with ViewModelFactory<TodoListViewModel> {
  final String categoryId;
  TodoListFactory(this.categoryId);
  
  @override
  TodoListViewModel build() => TodoListViewModel(categoryId);
  @override
  String? key() => "todos-$categoryId";
}

// 使用
TodoListViewModel get todosVM => 
  watchViewModel(factory: TodoListFactory(widget.categoryId));

Riverpod:

dart 复制代码
final todoListProvider = StateNotifierProvider.family
  .autoDispose<TodoListNotifier, List<Todo>, String>((ref, categoryId) {
    return TodoListNotifier(categoryId);
  });

// 使用
class TodoWidget extends ConsumerWidget {
  final String categoryId;
  
  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final todos = ref.watch(todoListProvider(categoryId));
    return ListView.builder(...);
  }
}

🔄 共享机制对比

flutter_view_model:基于Key的简单共享

dart 复制代码
// 场景:用户信息在多个页面共享
class UserProfileFactory with ViewModelFactory<UserViewModel> {
  @override
  String? key() => "current-user";  // 简单明了的共享标识
  @override
  UserViewModel build() => UserViewModel();
}

// 在任何地方使用,自动共享
final userVM = watchViewModel(factory: UserProfileFactory());

优势:

  • 🎯 语义清晰:相同key = 共享实例
  • ⚡ 性能优异:O(1)时间复杂度查找
  • 🧠 心智负担小:规则简单,一句话就能解释清楚

Riverpod:基于参数的智能共享

dart 复制代码
// 需要全局声明Provider
final userProvider = StateNotifierProvider.autoDispose
  .family<UserNotifier, UserState, String>((ref, userId) {
    return UserNotifier(userId);
  });

// 使用时
final user1 = ref.watch(userProvider("user1"));
final user2 = ref.watch(userProvider("user2"));

特点:

  • 🔒 类型安全:编译时检查
  • 🏗️ 参数化:自动为不同参数创建不同实例
  • 📚 学习成本:需要理解Provider、family、autoDispose等概念

📈 性能对比

内存管理

flutter_view_model

  • ✅ 自动销毁:当没有Widget绑定时自动dispose
  • ✅ 零配置:无需手动管理生命周期
  • ✅ 防泄漏:天然的内存泄漏保护机制

Riverpod

  • ⚠️ 需要配置:要记得使用autoDispose修饰符
  • ⚠️ 手动管理:复杂场景下需要careful的生命周期管理
  • ⚠️ 学习成本:需要理解何时使用autoDispose

查找效率

flutter_view_model

  • ⚡ O(1)时间复杂度通过key查找实例
  • 🎯 查找逻辑简单:key → factory → type cache

Riverpod

  • ⚡ 同样高效,但查找逻辑更复杂
  • 🏗️ 需要处理Provider依赖图和参数匹配

🎨 代码可读性对比

flutter_view_model:代码即文档

dart 复制代码
class ProfilePageState extends State<ProfilePage> 
    with ViewModelStateMixin<ProfilePage> {
  
  // 一眼就知道这里在获取用户ViewModel
  UserViewModel get userVM => 
    watchViewModel(factory: UserViewModelFactory());
  
  @override
  Widget build(BuildContext context) {
    // 直接访问,简单明了
    return Text("Hello ${userVM.name}");
  }
}

Riverpod:需要理解更多概念

dart 复制代码
class ProfilePage extends ConsumerStatefulWidget {
  @override ConsumerState<ProfilePage> createState() => _ProfilePageState();
}

class _ProfilePageState extends ConsumerState<ProfilePage> {
  @override
  Widget build(BuildContext context) {
    // 需要理解ref.watch的含义
    final userState = ref.watch(userProvider);
    return Text("Hello ${userState.name}");
  }
}

🏆 适用场景分析

flutter_view_model 更适合:

  1. 中小型项目:快速开发,不需要复杂的状态依赖
  2. 团队新手较多:学习成本低,容易上手
  3. 原型开发:快速验证想法,不被复杂概念束缚
  4. 简单状态管理:用户信息、主题设置、简单的业务状态
dart 复制代码
// 典型场景:主题切换
class ThemeFactory with ViewModelFactory<ThemeViewModel> {
  @override String? key() => "app-theme";
  @override ThemeViewModel build() => ThemeViewModel();
}

// 在任何地方都可以轻松使用
ThemeViewModel get themeVM => watchViewModel(factory: ThemeFactory());

Riverpod 更适合:

  1. 大型企业项目:需要严格的类型检查和完整的工具链
  2. 复杂状态依赖:Provider之间有复杂的依赖关系
  3. 团队规范化:需要统一的代码风格和最佳实践
  4. 异步状态处理:大量的网络请求和异步操作

💡 少即是多的设计哲学

flutter_view_model 的设计原则

  1. 单一职责:ViewModel只负责状态管理,Factory只负责实例创建
  2. 最小惊讶原则:API行为符合直觉,不需要查文档就能理解
  3. 开发者友好:相信开发者会正确使用,不为边界情况增加复杂度
  4. 渐进式复杂度:基础ViewModel满足80%场景,StateViewModel处理复杂状态

实际体现

dart 复制代码
// 90%的场景:简单的ViewModel
class CounterViewModel extends ViewModel {
  int _count = 0;
  int get count => _count;
  void increment() { _count++; notifyListeners(); }
}

// 10%的场景:结构化的StateViewModel
class TodoStateViewModel extends StateViewModel<TodoState> {
  TodoStateViewModel() : super(state: TodoState.initial());
  void addTodo(String title) => setState(state.addTodo(title));
}

🎯 选择建议

选择 flutter_view_model 如果:

  • ✅ 你希望快速上手,不被复杂概念困扰
  • ✅ 项目规模中等,不需要过度工程化
  • ✅ 团队追求简洁、实用的解决方案
  • ✅ 你相信"少即是多"的设计哲学

选择 Riverpod 如果:

  • ✅ 项目规模大,需要严格的类型检查
  • ✅ 团队有充足时间学习和培训
  • ✅ 需要复杂的异步状态处理和依赖管理
  • ✅ 希望使用完整的工具链和生态系统

🌟 结语

在技术选择上,并不是功能越多越好,复杂度越高越先进。flutter_view_model 用最简单的方式解决了80%的状态管理场景,让开发者能够专注于业务逻辑而不是状态管理的复杂性。

正如Antoine de Saint-Exupéry所说:"完美不是无以增加,而是无以删减"。在追求功能完整性的同时,我们也应该欣赏那些通过减法哲学带来的优雅和高效。

对于大多数Flutter项目来说,flutter_view_model 提供了一个既简单又强大的状态管理方案。它证明了有时候,少即是多不仅仅是一个设计理念,更是提升开发效率和代码质量的实际方法。


选择合适的工具,而不是最复杂的工具。让代码服务于业务,而不是让业务适应框架。

相关推荐
玖夜Kty1 分钟前
国内环境修改 flutter.bat 来设置 flutter 的网络环境
flutter
LinXunFeng1 小时前
Flutter - GetX Helper 助你规范应用 tag
flutter·github·visual studio code
明月看潮生3 小时前
青少年编程与数学 01-011 系统软件简介 07 iOS操作系统
ios·青少年编程·操作系统·系统软件
李斯维4 小时前
循序渐进 Android Binder(二):传递自定义对象和 AIDL 回调
android·java·android studio
90后的晨仔5 小时前
RxSwift 框架解析
前端·ios
可爱小仙子9 小时前
ios苹果系统,js 滑动屏幕、锚定无效
前端·javascript·ios
阅文作家助手开发团队_山神10 小时前
第五章:Flutter Quill渲染原理深度剖析:Delta到RichText的华丽转身
flutter
casual_clover11 小时前
Android Studio 解决首次安装时下载 Gradle 慢问题
android·ide·android studio
咕噜企业签名分发-淼淼14 小时前
开发源码搭建一码双端应用分发平台教程:逐步分析注意事项
android·ios