Riverpod场景下在FutureProvider内读取Provider的最佳实践是什么
Riverpod 该场景最佳实践
核心问题根因
导致userProvider无法正常释放的核心原因有两点:
- 代码笔误:
FutureProvider中调用的ref.watch(userApi)应为ref.watch(userApiProvider),错误的Provider引用会导致生命周期绑定异常 - 生命周期不匹配:未给
userApiProvider添加autoDispose修饰符,全局生命周期的API Provider被autoDispose类型的userProvider监听时,会阻碍userProvider的自动回收逻辑
现有代码合规性说明
已实现的将Reader函数传入API类构造的逻辑完全符合官方规范,属于官方推荐的服务类封装方式,无需调整。
最佳实践实现方案
分为两种场景可选:
场景1:API层Provider运行时无变更(绝大多数业务场景)
无需为API层建立监听依赖,直接使用ref.read读取API实例即可,既符合规范也不会产生多余的生命周期绑定:
// 给API层Provider添加autoDispose,无消费方时自动释放 final userApiProvider = Provider.autoDispose((ref) => UserApi(ref.read)); class UserApi { final Dio _dio; const UserApi(Reader read): _dio = read(dioProvider); Future<Response> getUser(String id, { CancelToken? cancelToken }) async{ final _url = '$URL_TO_API/$id'; return _dio.get(_url, cancelToken: cancelToken); } } final userProvider = FutureProvider.autoDispose.family<User, int>((ref, userId) async { // 静态依赖无需监听,直接用read读取 final userApi = ref.read(userApiProvider); final cancelToken = CancelToken(); ref.onDispose(() { cancelToken.cancel(); }); final response = await userApi.getUser(userId.toString(), cancelToken: cancelToken); return User.fromJson(response.data); });
场景2:API层Provider运行时可能变更(如动态切换测试/正式环境接口实现)
使用ref.watch建立监听,同时保证所有关联Provider都添加autoDispose修饰符即可:
// 必须添加autoDispose保证生命周期匹配 final userApiProvider = Provider.autoDispose((ref) => UserApi(ref.read)); class UserApi { final Dio _dio; const UserApi(Reader read): _dio = read(dioProvider); Future<Response> getUser(String id, { CancelToken? cancelToken }) async{ final _url = '$URL_TO_API/$id'; return _dio.get(_url, cancelToken: cancelToken); } } final userProvider = FutureProvider.autoDispose.family<User, int>((ref, userId) async { // 需响应依赖变更时用watch建立监听 final userApi = ref.watch(userApiProvider); final cancelToken = CancelToken(); ref.onDispose(() { cancelToken.cancel(); }); final response = await userApi.getUser(userId.toString(), cancelToken: cancelToken); return User.fromJson(response.data); });
注意事项
- 所有需要自动回收的Provider都必须添加
autoDispose修饰符,避免内存残留 - 官方禁止在Provider函数体内调用
read的场景仅针对需要响应变更的依赖,静态不变的依赖使用read完全合规 - 消费
userProvider的组件卸载时,Riverpod会自动触发所有关联Provider的autoDispose逻辑,无需手动处理释放
内容的提问来源于stack exchange,提问作者Fabrizio Tognetto
相关产品推荐
相关产品推荐

