Flutter Bloc中如何访问另一个Bloc的状态?
Flutter Bloc中如何访问另一个Bloc的状态?
下面提供三种实用方案解决MediaBloc获取UserBloc中token的问题:
方案一:构造函数注入UserBloc并监听状态
直接在MediaBloc初始化时传入UserBloc实例,监听其状态变化同步token,后续请求时直接使用同步后的token。
修改MediaBloc代码:
class MediaBloc extends Bloc<MediaEvent, MediaState> { final UserBloc userBloc; late StreamSubscription<UserState> _userSubscription; String? _currentToken; MediaBloc(this.userBloc) : super(MediaState(mediaList: [])) { // 监听UserBloc状态更新,同步token _userSubscription = userBloc.stream.listen((userState) { _currentToken = userState.token; }); on<FetchMediaEvent>((event, emit) async { if (_currentToken == null) { // 处理未登录场景,比如emit带错误的状态 emit(MediaState(mediaList: [], error: "用户未登录")); return; } List<Media> mediaList = await fetchUserMedia(token: _currentToken!); emit(MediaState(mediaList: mediaList)); }); } @override Future<void> close() { // 取消订阅,避免内存泄漏 _userSubscription.cancel(); return super.close(); } }
UI层提供Bloc实例时,通过context.read()获取UserBloc传入MediaBloc:
BlocProvider( create: (context) => UserBloc(), child: BlocProvider( create: (context) => MediaBloc(context.read<UserBloc>()), child: YourScreen(), ), )
方案二:在UI层获取token后触发MediaBloc事件
修改FetchMediaEvent让它携带token参数,在UI层触发事件前先从UserBloc获取token。
首先更新事件类:
class FetchMediaEvent { final String token; FetchMediaEvent(this.token); }
然后修改MediaBloc的事件处理:
class MediaBloc extends Bloc<MediaEvent, MediaState> { MediaBloc() : super(MediaState(mediaList: [])) { on<FetchMediaEvent>((event, emit) async { List<Media> mediaList = await fetchUserMedia(token: event.token); emit(MediaState(mediaList: mediaList)); }); } }
UI层触发事件时先获取token:
ElevatedButton( onPressed: () { final userState = context.read<UserBloc>().state; if (userState.token != null) { context.read<MediaBloc>().add(FetchMediaEvent(userState.token!)); } }, child: const Text("获取媒体列表"), )
如果需要在UserBloc状态变化时自动触发媒体请求,可用BlocListener:
BlocListener<UserBloc, UserState>( listener: (context, state) { if (state.token != null) { context.read<MediaBloc>().add(FetchMediaEvent(state.token!)); } }, child: YourScreen(), )
方案三:通过Repository层共享状态(推荐)
将token抽离到独立的Repository类中,UserBloc负责更新Repository的token,MediaBloc从Repository读取token,彻底解耦两个Bloc。
首先定义Repository:
class AuthRepository { String? _token; String? get token => _token; // 更新token的方法 void updateToken(String? newToken) { _token = newToken; } }
修改UserBloc,注入AuthRepository并更新token:
class UserBloc extends Bloc<UserEvent, UserState> { final AuthRepository authRepo; UserBloc(this.authRepo) : super(UserState(token: authRepo.token)) { // 示例:处理更新token的事件 on<UpdateUserTokenEvent>((event, emit) { authRepo.updateToken(event.token); emit(UserState(token: event.token)); }); } }
修改MediaBloc,注入AuthRepository并读取token:
class MediaBloc extends Bloc<MediaEvent, MediaState> { final AuthRepository authRepo; MediaBloc(this.authRepo) : super(MediaState(mediaList: [])) { on<FetchMediaEvent>((event, emit) async { final token = authRepo.token; if (token == null) { emit(MediaState(mediaList: [], error: "用户未登录")); return; } List<Media> mediaList = await fetchUserMedia(token: token); emit(MediaState(mediaList: mediaList)); }); } }
最后在App顶层提供Repository和Bloc:
RepositoryProvider( create: (context) => AuthRepository(), child: BlocProvider( create: (context) => UserBloc(context.read<AuthRepository>()), child: BlocProvider( create: (context) => MediaBloc(context.read<AuthRepository>()), child: YourApp(), ), ), )
内容的提问来源于stack exchange,提问作者shakky goyal
相关产品推荐
相关产品推荐

