Reputation: 562
I need to access AuthenticationBloc in my LoginBloc so I can fire the AuthenticationLogin() event if the login is successful. What I did so far is not working.
What I've done:
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
}
}
What I'm trying to accomplish:
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(),
);
}
}
As you can see, the user is currently in the LoginScreen, once the login is successful, I need to yield the AuthenticationAuthenticated() state in my AuthenticationBloc() so my users will be directed to the HomePage()
How can I yield the AuthenticationAuthenticated() state of the AuthenticationBloc() inside my LoginBloc() - since my login logic happens inside the LoginBloc.
Upvotes: 1
Views: 4762
Reputation: 562
_controller.add(AuthenticationStatus.authenticated);
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;
}
Upvotes: 2
Reputation: 1268
Here is one way to do it. You must call BlocBuilder to handles building the widget in response to new states.
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();
},
),
);
}
}
At first, the state is AuthenticationUnauthenticated and displays the login screen. If the login is successful then we display homepage, otherwise if it failed we will display 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
}
}
}
And here is the AuthenticationBloc () code which will handle the authentication.
class AuthenticationBloc extends Bloc<AuthenticationEvent, AuthenticationState>{
//code
Stream<AuthenticationState> mapEventToState(
AuthenticationEvent event,
) async* {
if(event is AuthenticationLogin) {
yield AuthenticationInProgress();
//code
yield AuthenticationAuthenticated();
}
}
}
Upvotes: 0