使用Riverpod时能否全局保存ref对象?如何在Dio拦截器中获取ref调用登出逻辑
解决方案
因为RequestInterceptor是普通Dart类,不属于Riverpod的Provider作用域,本身没有内置的ref对象,所以需要通过外部注入的方式传入ref或者对应的读取方法,常用两种实现方案:
方案1:构造函数注入Reader(优先推荐)
在创建Dio实例的Provider内部直接将ref.read方法注入到拦截器的构造函数中,符合Riverpod依赖注入的设计规范,无额外全局依赖。
第一步:修改拦截器代码
class RequestInterceptor extends InterceptorsWrapper { // 1.0.0-dev.7版本中Reader是ref.read方法的类型定义 final Reader read; RequestInterceptor(this.read); @override void onResponse(Response response, ResponseInterceptorHandler handler) { if (response.data['code'] == 404) { // 直接用注入的read方法调用登出逻辑 read(userProvider).logout(); } // 其余原有逻辑 super.onResponse(response, handler); } }
第二步:注册Dio Provider时传入read方法
final dioProvider = Provider<Dio>((ref) { final dio = Dio(); // 配置拦截器时直接把当前Provider的ref.read传进去 dio.interceptors.add(RequestInterceptor(ref.read)); // 其余Dio基础配置、其他拦截器添加逻辑 return dio; });
方案2:全局ProviderContainer注入
如果拦截器的初始化逻辑无法放在Provider内部,可以把根级ProviderContainer定义为全局变量使用,适合特殊场景。
第一步:定义全局container并绑定到应用根节点
// 全局声明ProviderContainer final globalContainer = ProviderContainer(); void main() { runApp( UncontrolledProviderScope( container: globalContainer, child: const MyApp(), ), ); }
第二步:拦截器内直接使用全局container读取Provider
@override void onResponse(Response response, ResponseInterceptorHandler handler) { if (response.data['code'] == 404) { globalContainer.read(userProvider).logout(); } super.onResponse(response, handler); }
注意:该方案需要谨慎使用,全局容器如果处理不当容易出现跨作用域的状态不一致问题,非必要场景优先选择方案1。
内容的提问来源于stack exchange,提问作者Liu Silong
相关产品推荐
相关产品推荐

