如何解决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
相关产品推荐
相关产品推荐

