You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.27 07:06:10