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

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显示的依然是旧状态。

解决方案

  1. 获取正确的Bloc实例发送事件
    登录成功后,通过context获取BlocProvider提供的UserBloc实例,再发送LoadUser事件:
// 登录成功后执行
context.read<UserBloc>().add(LoadUser());
  1. 登出时清理资源与重置状态
    添加登出事件,清理数据库订阅并重置状态,避免旧数据残留:
  • 在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());
  1. 确保DatabaseRepository.getUser()正确响应用户切换
    检查getUser()方法是否基于当前Firebase登录用户的ID获取数据,而非缓存旧数据。确保每次调用getUser()时,都能拉取当前登录用户的最新数据。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 06:21:29