I have a simple flow:
a UserModel
implementing ChangeProvider
which wraps the state of the user (if it is logged in and utilities to log him in/out). In particular logout looks like:
void logout() {
user = null;
notifyListeners();
}
a UserPage
widget with (among others):
class UserPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
// ... adding only relevant code
// a text with the user first letter of the email
Text(context.watch<UserModel>().user.email[0])
// a logout button with the following onPressed method
TextButton( \\ ...
onPressed: () {
context.read<UserModel>().logout();
Navigator.pop(context);
}
)
}
}
I was expecting that pressing logout and popping the UserPage
widget will not let flutter rebuild it. However it is not the case and the notifyListeners()
in logout
method makes flutter rebuild the widget and trigger a NullPointerException
(since the user is null and the email can't be accessed).
I could deal with it (checking if the user object is != null but I would like to understand why this happens).
Is it correct to assume pop
destroys the widget? If not, how should I handle this case?
When a user is logged out I don't want to have in memory this widget nor deal with its existence. I would expect to create a UserPage
when a user logs in and destroy it after its logout
When you call logout
, watch
in this line Text(context.watch<UserModel>().user.email[0])
will cause the widget it's in to rebuild.
You need to call logout
in the call back of push
the one you called to push this page. pop
can also send values to inform about the conditions like success or failure.
So it would be something like this:
Navigator.pushNamed(context, some_route).then(value) {
context.read<UserModel>().logout();
}
value
in the call back can be returned from pop
like so Navigator.of(context).pop(true);
This will ensure that logout
is only called after the widget has been popped.
If you don't like callbacks you can use async
await
pattern.