问题描述
我需要访问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();
}
}
}
,
- 我已将AuthenticationBloc预订到AuthenticateCredentialsUsecase类的状态流。
- 在我的LoginBloc中调用AuthenticateCredentialsUsecase并对凭据进行身份验证时...
- 然后我更新状态流-
_controller.add(AuthenticationStatus.authenticated);
- 反过来将触发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;
}