如何在另一个Cubit中从Authentication Cubit获取状态数据?
解决方案:在Posts Cubit中获取Authentication Cubit的Token
以下是几种符合Flutter Bloc/Cubit最佳实践的实现方式,你可以根据项目规模和需求选择:
方案一:直接注入AuthenticationCubit到PostsCubit
将AuthenticationCubit作为依赖传入PostsCubit,直接从其状态中获取Token,同时可以监听Auth状态变化来自动触发帖子刷新。
class PostsCubit extends Cubit<PostsState> { final AuthenticationCubit _authCubit; late StreamSubscription _authSubscription; PostsCubit(this._authCubit) : super(PostsInitial()) { // 监听Auth状态变化,Token更新时自动刷新帖子 _authSubscription = _authCubit.stream.listen((authState) { if (authState is User && authState.tokens?.accessToken != null) { fetchPosts(); } }); } Future<void> fetchPosts() async { final authState = _authCubit.state; if (authState is User && authState.tokens?.accessToken != null) { try { emit(PostsLoading()); final posts = await PostsApi.fetchPosts(authState.tokens!.accessToken); emit(PostsLoaded(posts)); } catch (e) { emit(PostsError(e.toString())); } } else { emit(PostsError('用户未登录或Token无效')); } } @override Future<void> close() { _authSubscription.cancel(); return super.close(); } }
优缺点:实现简单,适合小型项目;但PostsCubit与AuthenticationCubit耦合度高,不利于独立测试和解耦。
方案二:通过Repository层解耦(推荐)
引入Repository层封装API调用和Token获取逻辑,PostsCubit只依赖Repository,无需直接操作AuthenticationCubit,符合单一职责原则。
1. 实现AuthRepository
负责从AuthenticationCubit中获取Token:
class AuthRepository { final AuthenticationCubit _authCubit; AuthRepository(this._authCubit); String? get currentAccessToken { final state = _authCubit.state; return state is User ? state.tokens?.accessToken : null; } }
2. 实现PostsRepository
封装帖子API调用,依赖AuthRepository获取Token:
class PostsRepository { final AuthRepository _authRepo; final PostsApi _api; PostsRepository(this._authRepo, this._api); Future<List<Post>> fetchPosts() async { final token = _authRepo.currentAccessToken; if (token == null) throw Exception('未获取到有效Token'); return await _api.fetchPosts(token); } }
3. PostsCubit依赖PostsRepository
class PostsCubit extends Cubit<PostsState> { final PostsRepository _postsRepo; PostsCubit(this._postsRepo) : super(PostsInitial()); Future<void> fetchPosts() async { try { emit(PostsLoading()); final posts = await _postsRepo.fetchPosts(); emit(PostsLoaded(posts)); } catch (e) { emit(PostsError(e.toString())); } } }
优缺点:代码结构清晰,解耦性强,便于单元测试;需要额外编写Repository层代码,适合中大型项目。
方案三:全局TokenHolder管理Token
通过全局注入的TokenHolder存储Token,AuthenticationCubit更新状态时同步更新TokenHolder,PostsCubit直接从TokenHolder获取Token。
1. 全局注入TokenHolder
final getIt = GetIt.instance; class TokenHolder { String? accessToken; String? refreshToken; } // 在app初始化时注入 void setupLocator() { getIt.registerSingleton(TokenHolder()); }
2. AuthenticationCubit更新TokenHolder
class AuthenticationCubit extends Cubit<AuthenticationState> { final TokenHolder _tokenHolder; AuthenticationCubit(this._tokenHolder) : super(NoUser()); Future<void> signIn(String email, String password) async { emit(UserLoading()); final tokens = await AuthApi.signIn(email, password); // 同步更新全局Token _tokenHolder.accessToken = tokens.accessToken; _tokenHolder.refreshToken = tokens.refreshToken; emit(User(tokens: tokens)); } }
3. PostsCubit使用TokenHolder
class PostsCubit extends Cubit<PostsState> { final TokenHolder _tokenHolder; final PostsApi _api; PostsCubit(this._tokenHolder, this._api) : super(PostsInitial()); Future<void> fetchPosts() async { final token = _tokenHolder.accessToken; if (token == null) { emit(PostsError('用户未登录')); return; } try { emit(PostsLoading()); final posts = await _api.fetchPosts(token); emit(PostsLoaded(posts)); } catch (e) { emit(PostsError(e.toString())); } } }
优缺点:耦合度最低,PostsCubit无需依赖AuthenticationCubit;但需要确保Token的状态同步,容易出现不一致问题,适合对解耦要求极高的场景。
内容的提问来源于stack exchange,提问作者Matthew Trent
相关产品推荐
相关产品推荐

