【问题标题】:Dart: How to properly dispatch bloc event in another blocDart:如何在另一个 bloc 中正确调度 bloc 事件
【发布时间】:2020-12-06 15:58:11
【问题描述】:

我需要在我的 LoginBloc 中访问 AuthenticationBloc,以便在登录成功时触发 AuthenticationLogin() 事件。到目前为止我所做的没有工作。

我做了什么:

class LoginBloc extends Bloc<LoginEvent, LoginState> {
  final AuthenticationBloc authenticationBloc;
  final AuthenticateCredentialsUsecase authenticateCredentialsUsecase;

//code

  Stream<LoginState> mapEventToState(
    LoginEvent event,
  ) async* {
        //code
        authenticationBloc.add(AuthenticationLogin());
        yield LoginLoadSuccess();
        //code
  }
}

我想要完成的事情:

class _AppViewState extends State<AppView> {

  final _navigatorKey = GlobalKey<NavigatorState>();
  NavigatorState get _navigator => _navigatorKey.currentState;

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      navigatorKey: _navigatorKey,
      builder: (context, child) {
        return BlocListener<AuthenticationBloc, AuthenticationState>(
          listener: (context, state) {
             if (state is AuthenticationAuthenticated) {
                _navigator.pushAndRemoveUntil<void>(
                  HomePage.route(),
                  (route) => false,
                );
             }
             else if (state is AuthenticationUnauthenticated){
                _navigator.pushAndRemoveUntil<void>(
                  LoginScreen.route(),
                  (route) => false,
                );
             }
          },
          child: child,
        );
      },
      onGenerateRoute: (_) => SplashPage.route(),
    );
  }
}

如您所见,用户当前在 LoginScreen 中,一旦登录成功,我需要在 AuthenticationBloc() 中产生 AuthenticationAuthenticated() 状态,这样我的用户将被定向到 HomePage()

如何在我的 LoginBloc() 中产生 AuthenticationBloc() 的 AuthenticationAuthenticated() 状态 - 因为我的登录逻辑发生在 LoginBloc 中。

【问题讨论】:

  • 嗨!这并不完全清楚。如果登录成功,你想在 Authenticationlogin() 事件中做什么。导航到另一个页面?
  • 我需要调用 AuthenticationLogin() 事件,以便它可以产生新状态 - AuthenticationAuthenticated() 并导航到 HomePage()。我将编辑我的问题以使其更清楚,感谢您指出这一点

标签: dart bloc flutter-bloc


【解决方案1】:
  1. 我为 AuthenticationBloc 订阅了我的 AuthenticateCredentialsUsecase 类的状态流。
  2. 当在我的 LoginBloc 中调用 AuthenticateCredentialsUsecase 并验证凭据时...
  3. 然后我更新状态流 - _controller.add(AuthenticationStatus.authenticated);
  4. 哪个会触发 AuthenticationLogin 事件 在 AuthenticationBloc 中

身份验证块

 AuthenticationBloc({
    @required CheckAuthenticationStatusUsecase checkAuthenticationStatus,
    @required LogoutAuthenticatedUserUsecase logoutAuthenticatedUser,
    @required AuthenticateCredentialsUsecase authenticateCredentials,
  })  : assert(checkAuthenticationStatus != null),
        assert(logoutAuthenticatedUser != null),
        assert(authenticateCredentials != null),
        checkAuthenticationStatusUsecase = checkAuthenticationStatus,
        logoutAuthenticatedUserUsecase = logoutAuthenticatedUser,
        authenticateCredentialsUsecase = authenticateCredentials,
        super(AuthenticationInitial()) {
    add(AuthenticationStatusRequested());
    _loginStatusSubscription =
        authenticateCredentialsUsecase.status.listen((event) {
      if (event == AuthenticationStatus.authenticated) {
        add(AuthenticationLogin());
      }
    });
  }

AuthenticateCredentialsUsecase

  final _controller = StreamController<AuthenticationStatus>();

  Stream<AuthenticationStatus> get status async* {
    yield AuthenticationStatus.unknown;
    yield* _controller.stream;
  }

  void dispose() => _controller.close();

  @override
  Future<Either<Failure, AuthenticatedUser>> call(AuthenticationParams params) async {

    final result = await repository.authenticateCredentials(params.userName, params.password);

    if(result is Right){
      _controller.add(AuthenticationStatus.authenticated);
    }

    return result;
  }

【讨论】:

    【解决方案2】:

    这是一种方法。您必须调用 BlocBuilder 来处理构建小部件以响应新状态。

    class MyApp extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          theme: ThemeData(
            primarySwatch: Colors.blue,
            visualDensity: VisualDensity.adaptivePlatformDensity,
          ),
          debugShowCheckedModeBanner: false,
          home: BlocBuilder<AuthenticationBloc, AuthenticationState>(
            builder: (context, state) {
              //If the login is successful, show homepage
              if (state is AuthenticationAuthenticated) {
                return HomePage();
              }
              //If the login failed, show login screen
              if (state is AuthenticationUnauthenticated) {
                return LoginScreen();
              }
              //If the login is in process, show loading indicator
              if (state is AuthenticationInProgress) {
                return LoadingIndicator();
              }
              return SplashScreen();
            },
          ),
        );
      }
    }
    

    一开始,状态为AuthenticationUnauthenticated,并显示登录屏幕。如果登录成功,则显示主页,否则,如果登录失败,则显示 LoginScreen。

    class LoginBloc extends Bloc<LoginEvent, LoginState> {
      final AuthenticationBloc authenticationBloc;
      final AuthenticateCredentialsUsecase authenticateCredentialsUsecase;
    
    //code
    
      Stream<LoginState> mapEventToState(
        LoginEvent event,
      ) async* {
    
        if(event is LoginButtonPressed) {
            // some logic code
            // eg. : final response = UserRepository.login(username: event.username, password: event.password);
                authenticationBloc.add(AuthenticationLogin());
                //code
    
        }
            
      }
    }
    

    这是处理身份验证的 AuthenticationBloc () 代码。

     class AuthenticationBloc extends Bloc<AuthenticationEvent, AuthenticationState>{
        
        //code
        
          Stream<AuthenticationState> mapEventToState(
            AuthenticationEvent event,
          ) async* {
              if(event is AuthenticationLogin) {
                 yield AuthenticationInProgress();
                 //code
                 yield AuthenticationAuthenticated();
              }
        }
    }
        
    

    【讨论】:

    • 我的父小部件中有一个 BlocBuilder。而且我已经在实现您给出的代码,但我的问题是 - 我怎样才能在 LoginBloc() 中产生 AuthenticationBloc() 的 AuthenticationAuthenticated() 状态 - 因为我的登录逻辑发生在 LoginBloc
    • 不,您不能在 LoginBloc () 中产生 AuthenticationBloc () 的 AuthenticationAuthenticated () 状态。它只是 AuthenticationBloc () 它将从您拥有的状态管理小部件(屏幕)的显示!从 LoginBloc(),您可以向 AuthenticationBloc() 发出一个事件,后者将产生一个状态 AuthenticationAuthenticated() 并返回相应的小部件(这里是 HomePage())。我刚刚更新了我的代码
    • 好吧,但是如果你检查我上面的代码,我已经按照你说的做了,但是还是不行(小部件没有更新)
    • 你能再分享一些代码,以便我能妥善解决你的问题吗?
    • 嘿,谢谢你的帮助。我放弃了我的旧实现。相反,我将 AuthenticationBloc 订阅到 AuthenticateCredentialsUsecase 类的状态流,当凭据通过身份验证时,我会更新状态流,这反过来将触发 AuthenticationBloc 中的 AuthenticationLogin 事件
    猜你喜欢
    • 2020-12-07
    • 2020-03-23
    • 2021-06-17
    • 2019-12-06
    • 2023-03-24
    • 2019-05-23
    • 2021-02-05
    • 2023-03-15
    • 2019-10-28
    相关资源
    最近更新 更多