Reputation: 33
I have defined the following cubit.
@injectable
class AuthCubit extends Cubit<AuthState> {
final IAuthService _authService;
AuthCubit(this._authService) : super(const AuthState.initial());
void authCheck() {
emit(_authService.signedInUser.fold(
() => AuthState.unauthenticated(none()),
(user) => AuthState.authenticated(user),
));
}
}
But the BlocListener which listens to this bloc is not getting invoked even after emit
is called. But everything works as expected when I add a zero delay before the emit call.
Future<void> authCheck() async {
await Future.delayed(Duration.zero);
emit(_authService.signedInUser.fold(
() => AuthState.unauthenticated(none()),
(user) => AuthState.authenticated(user),
));
}
I tried out this delay because for other events which made some backend call (with some delay) emit worked perfectly. But I'm pretty sure this is not how it should work. Am I missing something here?
EDIT: Adding the SplashPage widget code which uses BlocListener.
class SplashPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return BlocListener<AuthCubit, AuthState>(
listener: (context, state) {
print(state);
},
child: Scaffold(
body: Center(
child: CircularProgressIndicator(),
),
),
);
}
}
Place where authCheck() is called,
class App extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MultiBlocProvider(
providers: [
BlocProvider<AuthCubit>(
create: (_) => getIt<AuthCubit>()..authCheck(),
),
],
child: MaterialApp(
....
),
);
}
}
and the AuthState is a freezed
union
@freezed
abstract class AuthState with _$AuthState {
const factory AuthState.initial() = _Initial;
const factory AuthState.authenticated(User user) = _Authenticated;
const factory AuthState.unauthenticated(Option<AuthFailure> failure) = _Unauthenticated;
const factory AuthState.authInProgress() = _AuthInProgress;
}
Also, when I implemented a bloc (instead of Cubit) with the same functionality, everything worked as expected.
Upvotes: 0
Views: 724
Reputation: 1109
For me, the delay does not work perfectly. So I found this solution, maybe help someone:
@override
void initState() {
super.initState();
WidgetsBinding.instance?.addPostFrameCallback((_) async {
await myCubit.doSomethingFun();
});
}
And @Pieter is right, listener only be invoked when the widget is built.
Upvotes: 1
Reputation: 5648
Without the delay the emit is called directly from the create method of the provider. This means that the listener is not (completely) built yet and thus there is no listener to be called when you emit the state.
So by adding the delay you allow the listener to subscribe to the stream first and thus it gets called when you emit the new state.
Upvotes: 1