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

如何解决Flutter中Auth组件的循环依赖问题(含401拦截需求)

循环依赖问题与401拦截需求解决

问题背景

  • 循环依赖链:AuthRepository -> AuthDataSource -> ApiClient -> AuthInterceptor -> AuthRepository
  • 核心需求:在AuthInterceptor中实现网络请求拦截,当响应码为401(未认证状态)时,调用AuthRepository.logout()方法

当前依赖注入代码

final sl = GetIt.instance; // sl is short for service locator

sl.registerLazySingleton<AuthInterceptor>(() => AuthInterceptor(authRepository: sl()));

sl.registerLazySingleton<ApiClient>(
      () => ApiClient(dio: Dio(), preferencesService: sl(), authInterceptor: sl(), tokenStorage: sl()));

sl.registerLazySingleton<AuthRepository>(() => AuthRepositoryImpl(authDataSource: sl()));

sl.registerLazySingleton<AuthDataSource>(() => AuthRemoteDataSourceImpl(apiClient: sl()));

解决循环依赖的可行方案

方案1:延迟获取依赖

修改AuthInterceptor,不在构造时注入AuthRepository,而是在触发401逻辑时从服务定位器中直接获取:

class AuthInterceptor extends Interceptor {
  @override
  void onResponse(Response response, ResponseInterceptorHandler handler) {
    if (response.statusCode == 401) {
      // 延迟获取AuthRepository实例
      final authRepo = GetIt.instance<AuthRepository>();
      authRepo.logout();
    }
    super.onResponse(response, handler);
  }
}

// 调整注册逻辑,无需传入authRepository
sl.registerLazySingleton<AuthInterceptor>(() => AuthInterceptor());

方案2:事件总线解耦

通过事件总线实现AuthInterceptor与AuthRepository的解耦,避免直接依赖:

// 定义未授权事件
class UnauthorizedEvent {}

// AuthInterceptor中发送事件
class AuthInterceptor extends Interceptor {
  final EventBus eventBus;

  AuthInterceptor(this.eventBus);

  @override
  void onResponse(Response response, ResponseInterceptorHandler handler) {
    if (response.statusCode == 401) {
      eventBus.fire(UnauthorizedEvent());
    }
    super.onResponse(response, handler);
  }
}

// AuthRepository中监听事件并执行logout
class AuthRepositoryImpl implements AuthRepository {
  final AuthDataSource authDataSource;
  final EventBus eventBus;

  AuthRepositoryImpl(this.authDataSource, this.eventBus) {
    // 监听未授权事件
    eventBus.on<UnauthorizedEvent>().listen((_) => logout());
  }

  @override
  Future<void> logout() async {
    // 实现具体的注销逻辑
  }
}

// 调整依赖注册顺序
sl.registerLazySingleton<EventBus>(() => EventBus());
sl.registerLazySingleton<AuthInterceptor>(() => AuthInterceptor(sl()));
sl.registerLazySingleton<AuthRepository>(() => AuthRepositoryImpl(sl(), sl()));
// 其余注册代码保持不变

方案3:调整注册模式

利用GetIt的工厂注册特性,调整依赖注册顺序以支持循环依赖(仅适用于部分场景):

// 先注册AuthRepository为工厂模式
sl.registerFactory<AuthRepository>(() => AuthRepositoryImpl(authDataSource: sl()));
// 再注册AuthInterceptor
sl.registerLazySingleton<AuthInterceptor>(() => AuthInterceptor(authRepository: sl()));
// 其余注册代码保持不变

注意:工厂注册每次获取都会生成新实例,若需单例可结合registerSingleton延迟初始化。

内容的提问来源于stack exchange,提问作者Faizan Malik

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 16:33:22