flutter_bloc: ^8.0.0状态不更新:用户切换后bloc留存旧数据
问题分析与解决方案
问题描述
我有一个用Firebase存储用户数据的Bloc,正常使用没问题,但用户登出后重新登录时,Bloc状态无法更新为新用户的数据。比如:User_1(姓名:one)登出,接着User_2(姓名:two)登录,Bloc状态依然保留User_1的数据。
相关代码如下:
user_state.dart
part of 'user_bloc.dart'; class UserState extends Equatable { const UserState(); @override List<Object?> get props => []; } class UserLoading extends UserState { const UserLoading(); @override List<Object> get props => []; } class UserLoaded extends UserState { final UserFindine user; UserLoaded({required this.user}); @override List<Object> get props => [user]; }
user_event.dart
part of 'user_bloc.dart'; class UserEvent extends Equatable { const UserEvent(); @override List<Object> get props => []; } class LoadUser extends UserEvent { const LoadUser(); @override List<Object> get props => []; } class UpdateUser extends UserEvent { final UserFindine user; const UpdateUser(this.user); @override List<Object> get props => [user]; }
user_bloc.dart
class UserBloc extends Bloc<UserEvent, UserState> { final DatabaseRepository _databaseRepository; StreamSubscription? _databaseSubscription; UserBloc({ required DatabaseRepository databaseRepository, }) : _databaseRepository = databaseRepository, super(UserLoading()) { on<LoadUser>((event, emit) { _databaseSubscription?.cancel(); _databaseSubscription = _databaseRepository.getUser().listen((user) { add(UpdateUser(user)); }); }); on<UpdateUser>((event, emit) { final data = event.user; // 这里的数据是正确的 emit(UserLoaded(user: data)); }); } }
我尝试在用户登录时触发LoadUser事件,但还是获取旧用户数据。请问我哪里做错了?感谢帮助🔥
补充说明:
在main.dart文件中:
MultiBlocProvider( providers: [ BlocProvider<AuthBloc>( create: (context) => AuthBloc( authRepository: context.read<AuthRepository>(), ), ), BlocProvider( create: (_) => UserBloc(databaseRepository: DatabaseRepository())..add(LoadUser()), ), ], ),
同时,我在登录事件后执行以下代码:
UserBloc(databaseRepository: DatabaseRepository())..add(LoadUser());
核心问题
你登录时新建了一个UserBloc实例,而非使用BlocProvider中已注入的那个。执行UserBloc(databaseRepository: DatabaseRepository())..add(LoadUser())会创建一个全新的Bloc对象,这个对象和UI层监听的Bloc完全无关,所以UI显示的依然是旧状态。
解决方案
- 获取正确的Bloc实例发送事件
登录成功后,通过context获取BlocProvider提供的UserBloc实例,再发送LoadUser事件:
// 登录成功后执行 context.read<UserBloc>().add(LoadUser());
- 登出时清理资源与重置状态
添加登出事件,清理数据库订阅并重置状态,避免旧数据残留:
- 在
user_event.dart中新增事件:
class LogoutUser extends UserEvent { const LogoutUser(); @override List<Object> get props => []; }
- 在
user_bloc.dart中处理该事件:
on<LogoutUser>((event, emit) { _databaseSubscription?.cancel(); emit(UserLoading()); // 也可以自定义UserUnloaded状态 });
- 登出时触发该事件:
context.read<UserBloc>().add(LogoutUser());
- 确保DatabaseRepository.getUser()正确响应用户切换
检查getUser()方法是否基于当前Firebase登录用户的ID获取数据,而非缓存旧数据。确保每次调用getUser()时,都能拉取当前登录用户的最新数据。
内容的提问来源于stack exchange,提问作者Emre
相关产品推荐
相关产品推荐

