Reputation: 98
I have a flutter app that implements firebase authentication. After following this tutorial my main.dart file looks like this:
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return StreamProvider<User>.value(
catchError: (_, err) => null,
value: AuthService().user,
child: MaterialApp(
home: Wrapper(),
),
);
}
}
Where the value: AuthService().user is returned as a stream by the following get function:
// auth change user stream
Stream<User> get user {
return _auth.onAuthStateChanged.map(
(FirebaseUser user) => _userFromFirebaseUser(user),
);
}
User _userFromFirebaseUser(FirebaseUser user) {
return user != null ? User(uid: user.uid) : null;
}
And the Wrapper() widget looks like this:
class Wrapper extends StatelessWidget {
@override
Widget build(BuildContext context) {
final user = Provider.of<User>(context);
if (user == null) {
print("user is null, should show Authenticate()");
return Authenticate();
} else {
return Home();
}
}
}
This code functions when:
However, from the Home() screen navigation is laid out as such:
I use Navigator.push() when going forward (i.e. from "SecondPage()" to "ThirdPage()"). I then wrapped both Secondary and Third page scaffolds in a WillPopScope, where the onWillPop calls Navigator.pushReplacement() to navigate backwards.
(Note: I did this because these pages read and write data from firebase firestore, and Navigator.pop() does not cause a rerender. This means the user may update something on the ThirdPage() that changes a value in firestore but when I then call Navigator.pop() it doesn't update the SecondPage() with the new data.)
My issue is, something about the Navigator.pushReplacement() when navigating from the SecondPage() to the Home() page is causing an issue so that when the user then logs out, the screen does not show the Authenticate() page.
I have placed a print("user is null, should show Authenticate()")
call in the Wrapper() to verify that if (user == null)
is true when the user clicks the logout button. It does print however it still doesn't show the Authenticate() screen.
I know it has something to do with the pushReplacement(), as logging out directly from Home() without having navigated anywhere functions correctly (i.e. Authenticate() page is shown). Any help is appreciated.
Upvotes: 2
Views: 1276
Reputation: 2773
I got the same issue while following the same tutorial. In my case, it turned out signUp button works fine but for both log-out and sign-in I need to refresh to see changes. After debugging a file I came to this conclusion.
Even though the stream always listens to the incoming data, it is inside the Widget build method and needs to be called to get another stream to. So I just needed to call the
Wrapper()
method once I detect a non-null user value.
So I did this.
Navigator.pushAndRemoveUntil(context, MaterialPageRoute(builder: (context)=>
Wrapper()), (_) => false );
I made an if-else
statement in the signIn
page, and when user returned non-null I called the Wrapper()
once again and it did the trick.
Upvotes: 4
Reputation: 21
I ran into the exact same problem and I chose to explicitely navigate back to the Wrapper when user logs out with something like that :
void signOut(BuildContext context) {
Auth().handleSignOut();
Navigator.pushAndRemoveUntil(
context,
MaterialPageRoute(builder: (context) => Wrapper()),
(_) => false
);
}
I still listen to the stream in a Provider to void user data for security reasons but I don't rely on this listener to get back to the initial screen.
void initAuthListener(){
userStream = Auth().user;
userStream.listen((data) {
if(data==null){
voidUser();
}else{
setUser(data);
}
}, onDone: () {
print("Task Done");
}, onError: (error) {
print("Some Error");
});
}
Having said that I'd be happy if anyone could shed some light on why the Wrapper is not rebuilt in our initial case.
Another thing, you mention "I did this because these pages read and write data from firebase firestore, and Navigator.pop() does not cause a rerender." I would suggest you to use Streams to retrieve data from firestore and Streambuilders to display them as explained in get to know firebase playlist. This will simplify and should improve offline experience.
Upvotes: 2