简体   繁体   English

flutter_bloc: ^8.0.0 state 不更新

[英]flutter_bloc: ^8.0.0 state does not updating

I have a bloc that keeps user data -via firebase- on the state. It works as it is but when the user signs out and sign in again, I can't update the bloc with new user data.我有一个 bloc,它通过 firebase 将用户数据保存在 state 上。它按原样工作,但是当用户注销并再次登录时,我无法使用新的用户数据更新 bloc。

Eg.例如。

User_1 (name: one) signs out. User_1(姓名:一)注销。 Then User_2 (name: two) signs in. Bloc state still keeping data from User_1然后 User_2(姓名:二)登录。Bloc state 仍然保留来自 User_1 的数据

user_state.dart用户状态.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 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 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; // This data is right.
      emit(UserLoaded(user: data));
    });
  }
}

I've tried to trigger LoadUser event when the user signs in. But still getting old user data.我试图在用户登录时触发 LoadUser 事件。但仍然获取旧用户数据。 Am I missing something?我错过了什么吗?

Thanks for any help谢谢你的帮助

Edit:编辑:

In my main.dart file:在我的 main.dart 文件中:

MultiBlocProvider(
        providers: [
          BlocProvider<AuthBloc>(
            create: (context) => AuthBloc(
              authRepository: context.read<AuthRepository>(),
            ),
          ),
          BlocProvider(
            create: (_) => UserBloc(databaseRepository: DatabaseRepository())..add(LoadUser()),
          ),
        ],
),

Also I use this after sign in event.我也在登录事件后使用它。

UserBloc(databaseRepository: DatabaseRepository())..add(LoadUser());

Similar happened to me when i had more than one instance of LoginBloc.当我有多个 LoginBloc 实例时,类似的情况发生在我身上。 In the case of normal pages, it's useful to recreate the Bloc, but for the login, you do not want to have more than one instance of it or re-create it when you navigate.在普通页面的情况下,重新创建 Bloc 很有用,但对于登录,您不希望拥有它的多个实例或在导航时重新创建它。

here is an example using AppRouter which contains a normal Bloc and a login Bloc, pls check the difference.这是一个使用 AppRouter 的示例,其中包含一个普通 Bloc 和一个登录 Bloc,请检查差异。 i added some comments to the code.我在代码中添加了一些注释。

you might also try to put a breakpoint to the MultiblocProvider in your code to see if it's called more than once.您也可以尝试在您的代码中为 MultiblocProvider 设置一个断点,以查看它是否被多次调用。

class AppRouter {
  late Repository repository;
  LoginCubit? loginCubit; //declare global login Bloc

  AppRouter() {
    repository = Repository(apiClient: ApiClient());
    loginCubit = LoginCubit(repository: repository); //create the Bloc once
  }

  Route? generateRoute(RouteSettings settings) {
    switch (settings.name) {
      case "/":
        return MaterialPageRoute(
          builder: (_) => BlocProvider.value( // use Blocprovider.value which will not create a new Bloc but use the one declared before
            value: loginCubit!,
            child: const LoginPage(key: null),
          ),
        );
      case "/main_page":
        final args = settings.arguments as Map;
        return MaterialPageRoute(
          builder: (_) => BlocProvider(
            create: (context) =>
                OtherCubit( repository: repository),
            child: OtherPage(),
          ),
        );  
     }
   }
}

Just add emit(UserLoading());只需添加emit(UserLoading()); above the line of final data = event.user;final data = event.user; Because once UserLoaded state is emitted and again you want to emit the same state, it will not rebuild BlocBuilder so I prefer always emit two different states in one method.因为一旦发出UserLoaded state 并且您想要再次发出相同的 state,它不会重建BlocBuilder ,所以我更喜欢始终在一种方法中发出两种不同的状态。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM