Closed fvisticot closed 5 years ago
@fvisticot can you share the full code? How is the settings page displayed? Is it pushed onto the navigation stack? If so you'll need to pop it off when you dispatch the LoggedOut
event.
My application is using the navigation stack You are right, if I set this code it is OK and I can see the login page. Is it what you said ?
BUT the builder is not called with the new state .... :( it is normal ?
void _logout() {
AuthenticationBloc authenticationBloc =
BlocProvider.of<AuthenticationBloc>(context);
authenticationBloc.dispatch(LoggedOut());
ApplicationSecureStorage().clear();
Navigator.of(context)
.pushNamedAndRemoveUntil('/login', (Route<dynamic> route) => false);
}
@fvisticot it's because you are using pushNamedAndRemove
which is removing the BlocBuilder
. I would recommend you use Navigator.pop()
instead.
Closing this for now. Please let me know if you're still having trouble 👍
Sorry to disturb you again but it is not clear for me.
The blocBuilder is created in a statefull Widget initialized in the main->runApp function.
I do not understand why the builder(context, state) method is not called when logout occurs (with or without pop function)...
Why the navigation stack can modify the mechanism ?
@fvisticot no problem! Can you please share the full code?
I'm guessing when you push the settings page you are removing the root page which has the BlocBuilder
. Can you confirm that you are always just using Navigator.push
and Navigator.pop
instead of pushReplacement
or pushNamedAndRemove
? Those will destroy the navigation stack below and dispose the widget that had BlocBuilder
.
You are the boss !!!! Thanx the lot... I was using a pushReplacement :( ... changing to push solve the pb !! Congratulation for your framework !!
@felangel hey, would you be able to provide some pointers to any doc/tutorial that describes how to use navigation (e.g. with a drawer) alongside the bloc package? I find it quite hard to understand what's going on here -- I've tried just using push (nothing like pushRemove and pushReplacement) to display a sub-page, e.g.
ListTile(
title: Text("Account"),
trailing: Icon(Icons.account_circle),
onTap: () {
Navigator.of(context).pop();
Navigator.of(context).push(MaterialPageRoute(
builder: (BuildContext context) => AccountScreen()));
},
but on the AccountScreen
return RaisedButton(
onPressed: () {
BlocProvider.of<AuthenticationBloc>(context).dispatch(
LoggedOut(),
);
},
child: Text('Sign Out'),
.. this doesn't work (the BlocProvider in the original tree (that's the parent of the drawer) doesn't get the callback). Maybe I could get it working by trial-and-error but it'd be better to understand what's going on. Thanks.
What I ended up doing is just calling
Navigator.of(context)
.pushReplacement(MaterialPageRoute(builder: (context) => App()));
after pressing logout, which looks a bit nasty (as this should be done through events, not imperatively).
Edit:
ah-ha, so based on your commit elsewhere https://github.com/boukmi/flutter_login/pull/1/commits/520885891b5cde3f93e5aab02ebe450a1094f2c3 .. I now pop the accountScreen before dispatching the LoggedOut() event, and everything works. Good, though I need to wrap my head around how to make this elegant. :)
@matevarga in flutter_bloc
v0.11.0 we introduced BlocListener
which is the recommended way to handle navigation or other "one-time actions" in response to state changes.
Check out the SnackBar Recipe for an example of how to show a SnackBar in response to a state change. Navigation should be handled in the same way in order to keep the builder function a pure function with no side effects.
Thanks @felangel I'll take a look.
BlocListener
which is the recommended way to handle navigation or other "one-time actions" in response to state changes.
So you mean that with this, i can use pushReplacementNamed
?
I think there are legit use cases for it, for instance in my app I have a page that i want to show at the first login only in order to let the user select one first initial setup and then just go back to the normal flow of the app, using pushReplacementNamed
i don't have the go back button in my AppBar
.
How can i do accomplish with flutter_bloc
?
EDIT: even pushNamed
can cause the issue? because i change my code like that but it's still not working as expected
@nerder have you checked out the navigation recipe?
I believe using BlocListener
should work just fine for your use case. Do you mind sharing a gist or link to a sample app? Thanks!
@felangel can you please check this question once. https://stackoverflow.com/questions/57343887/flutter-navigator-pop-keeps-the-dialog-box-partially-visible-with-black-shadow
Hi @felangel ! First, Thank you for the awesome package and great support to the Community. I've facing same issues. I used the Navigation Stack as you describe above. I've observed the Transition, the state changes correctly but BlocBuider doesn't rebuild.
My app has 2 pages: Home and Filter and uses 1 Bloc. Everything works fine on Home page but when I push to Filter page and trigger event then pop back to Home page, state and data return correctly but BlocBuilder not change.
Can you check my repos: https://github.com/lehaidangdev/football_players_app
Thanks
Instance of 'PlayerListingBloc' - FilterEvent Instance of 'PlayerListingBloc' - Transition { currentState: PlayerListingInitialState, event: FilterEvent, nextState: PlayerListingFetchingState } Request: _/api/players/s?minOverall=85&maxOverall=90&position= status: 200 Instance of 'PlayerListingBloc' - Transition { currentState: PlayerListingFetchingState, event: FilterEvent, nextState: PlayerListingFetchedState }
Hi @lehaidangdev 👋
Thanks for the positive feedback! I took a look at your app and I believe the problem is you're creating multiple instances of the PlayerListingBloc
. There is one being created by BlocProvider
in home.dart
which looks good but then in the initState
of filter.dart
you are creating another instance so when you add events to the _playerBloc
from filter.dart
it is a different bloc instance than the one on home which is why home's BlocBuilder does not update.
Hope that helps 👍
Thanks @felangel for suggestions. 😁
Hello @Felix, i am facing a similar problem where i am firing an event, which goes to the bloc but doesnt emit any state. I found this when i logged the on change using Bloc Observer. Below is where i am firing the event.
This is my bloc.
The above print statements can be seen on the console, but there is no state emitted. Any help will be appreciated.
Had the same. In my case was problem with using BlocProvider.value instead of BlocProvider(create: ...).
screen B -pop()-> screen A (should use BlocProvider(create: BlocA()) but was used BlocProvider.value(value: BlocA()))
flutter_bloc: ^0.7.0
I have adapted your login sample to my app.
when i try to logout, the bloc is correctly triggered and change the state to AuthenticationUnauthenticated
BUT the BlocBuilder => builder method is not triggered ... and the login page is not displayed
in the settings page to logout: