Flutter Riverpod 2中如何用AsyncNotifier实现删除并本地刷新页面
问题
项目中有两个AsyncNotifier(及对应Provider):
- 一个是从REST API获取待办事项列表的
AsyncNotifier<List> - 另一个是按ID删除待办事项的
AsyncNotifier
在展示待办列表的页面/组件中监听删除待办的Notifier,点击删除按钮后显示成功/失败的SnackBar。相关代码如下:
构建方法中的监听与列表获取:
ref.listen<AsyncValue<void>>( deleteTodoControllerProvider, (_, state) => state.whenOrNull( error: (error, stackTrace) { ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text(error.toString())), ); }, ), ); final todoList = ref.watch(todoListControllerProvider);
删除按钮的onPressed方法:
ref.read(deleteTodoControllerProvider.notifier).deleteTodoById(todo.id!);
需求:删除待办后不重新调用API,通过本地更新列表状态(如removeWhere)刷新页面。尝试调用todoListProvider.invalidate()会触发重复API请求,询问在待办列表Notifier中添加方法修改状态是否可行?
解决方案
完全可行,这是处理本地状态更新的合理方案,具体实现步骤如下:
- 在列表Notifier中添加本地更新方法
在负责待办列表的AsyncNotifier<List<Todo>>里新增一个方法,用于从本地状态中移除指定ID的待办:
class TodoListNotifier extends AsyncNotifier<List<Todo>> { @override FutureOr<List<Todo>> build() async { // 初始从API获取列表的逻辑 return await fetchTodosFromApi(); } // 新增本地移除待办的方法 void removeTodoLocally(String todoId) { final currentList = state.value; if (currentList != null) { // 创建新列表(遵循不可变状态原则),移除目标ID的待办 final updatedList = currentList.where((todo) => todo.id != todoId).toList(); // 更新状态为新的AsyncData包裹的列表 state = AsyncData(updatedList); } } }
- 修改删除Notifier的逻辑,成功后触发本地更新
在DeleteTodoNotifier的删除方法中,当API请求成功后,调用列表Notifier的本地更新方法:
class DeleteTodoNotifier extends AsyncNotifier<void> { @override FutureOr<void> build() {} Future<void> deleteTodoById(String todoId) async { state = const AsyncLoading(); try { // 调用API执行删除操作 await api.deleteTodo(todoId); state = const AsyncData(null); // 删除成功后,触发列表的本地状态更新 ref.read(todoListControllerProvider.notifier).removeTodoLocally(todoId); } catch (e, stackTrace) { state = AsyncError(e, stackTrace); } } }
- 保留原有错误提示逻辑
你原来的ref.listen代码可以继续保留,用来处理删除失败时的SnackBar提示,无需修改。
这种方案的优势:
- 避免重复调用API,提升页面响应速度
- 符合Riverpod的不可变状态管理原则,通过创建新列表而非修改原列表来更新状态
- 逻辑分工清晰:列表Notifier负责维护列表状态,删除Notifier负责处理API请求及触发本地更新
内容的提问来源于stack exchange,提问作者S. M. JAHANGIR
相关产品推荐
相关产品推荐

