Dart:如何在另一个集团中正确调度集团事件

问题描述

我需要访问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(),);
             }
          },child: child,);
      },onGenerateRoute: (_) => SplashPage.route(),);
  }
}

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

由于我的登录逻辑发生在LoginBloc内部,因此如何在LoginBloc()内部产生AuthenticationBloc()的AuthenticationAuthenticated()状态。

解决方法

这是一种方法。您必须调用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();
          }
    }
}
    
,
  1. 我已将AuthenticationBloc预订到AuthenticateCredentialsUsecase类的状态流。
  2. 在我的LoginBloc中调用AuthenticateCredentialsUsecase并对凭据进行身份验证时...
  3. 然后我更新状态流-_controller.add(AuthenticationStatus.authenticated);
  4. 反过来将触发AuthenticationLogin事件 在AuthenticationBloc内部

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;
  }