为何、何时及如何使用RiverpodGenerator?对比CRUD+模型方案
为什么要用RiverpodGenerator和Freezed?
先聊Freezed:
手动写数据模型时,你是不是总在重复写copyWith、toString、==这类方法?不仅麻烦,还容易漏字段或者写错逻辑。Freezed就是帮你自动生成这些样板代码的工具,而且它天生支持不可变对象——这对状态管理至关重要,能避免意外修改数据导致的隐性bug。另外,Freezed的密封类(sealed class)可以轻松实现状态的多分支处理,比如请求数据时的「加载中/成功/失败」三种状态,不用手动写一堆嵌套if-else,代码逻辑会清晰很多。
再讲RiverpodGenerator:
Riverpod本身是个灵活的状态管理库,但手动写Provider(比如StateNotifierProvider、AsyncNotifierProvider)时,要写不少重复代码:定义Provider实例、关联Notifier、处理类型参数……RiverpodGenerator用注解(比如@riverpod)就能自动帮你生成这些代码,不仅减少手写量,还能避免类型不匹配这类低级错误。同时,它还能自动处理依赖关系,让你的状态管理代码更简洁、更易维护。
RiverpodGenerator的适用场景
- 中大型项目:当你的状态数量多、依赖关系复杂时,Generator能大幅减少样板代码,降低维护成本,避免代码冗余。
- 需要处理异步状态的场景:比如网络请求、本地数据库操作,用
AsyncNotifier结合Generator,能自动帮你管理「加载中/成功/失败」的状态,不用手动维护状态枚举。 - 团队协作项目:统一状态管理的写法,减少不同成员的代码风格差异,新人上手更快。
- 嫌手动写Provider麻烦的场景:如果你觉得手动创建Provider的步骤繁琐,Generator能让你用几行注解搞定原本十几行的代码。
如何使用RiverpodGenerator
- 添加依赖:在
pubspec.yaml中添加以下依赖:
dependencies: riverpod_annotation: ^2.3.0 dev_dependencies: riverpod_generator: ^2.3.0 build_runner: ^2.4.0
- 定义Notifier类:用
@riverpod注解你的Notifier,Generator会自动生成对应的Provider。比如实现一个待办列表的状态管理:
import 'package:riverpod_annotation/riverpod_annotation.dart'; part 'todo_list.g.dart'; @riverpod class TodoList extends _$TodoList { // 初始化状态 @override List<String> build() { return []; } // 添加待办的方法 void addTodo(String todo) { state = [...state, todo]; } // 删除待办的方法 void removeTodo(String todo) { state = state.where((item) => item != todo).toList(); } }
- 生成代码:运行build_runner命令生成对应的Provider代码:
# Flutter项目 flutter pub run build_runner build # Dart项目 dart run build_runner build
- 在UI中使用:通过
ref.watch监听状态,通过ref.read调用Notifier的方法:
// 监听待办列表状态 final todos = ref.watch(todoListProvider); // 添加待办 ElevatedButton( onPressed: () { ref.read(todoListProvider.notifier).addTodo("新的待办"); }, child: const Text("添加待办"), )
- 结合Freezed优化状态:如果需要处理异步状态,比如从网络加载数据,可以用Freezed定义密封类状态,再结合Generator:
// 用Freezed定义状态 @freezed class TodoState with _$TodoState { const factory TodoState.loading() = _Loading; const factory TodoState.success(List<Todo> todos) = _Success; const factory TodoState.error(String message) = _Error; } // 用Generator定义AsyncNotifier @riverpod class TodoRepository extends _$TodoRepository { @override TodoState build() { return const TodoState.loading(); } Future<void> fetchTodos() async { try { final todos = await api.fetchTodos(); state = TodoState.success(todos); } catch (e) { state = TodoState.error(e.toString()); } } }
内容的提问来源于stack exchange,提问作者Mohammed M
相关产品推荐
相关产品推荐

