Rebuild app or delete cache when redirect to home page Flutter - flutter

I have an app where when I logout with Firebase Auth, user's datas are still there, and I need to Hot restart the app to totally remove them.
I didn’t find a way to improve the signout method, so I want to try to rebuild app when user logout, or maybe delete the cache so user’s datas will no longer exist in app.
I have done some research but I can’t find any solution that can help me.
EDIT : Here's how I logout
Future<void> signOut() async {
await FirebaseAuth.instance
.signOut()
.then((value) => print('Sign Out'))
.onError((error, stackTrace) => print('Error in signed out'));
}
IconButton(
onPressed: () async {
await signOut();
Navigator.of(context, rootNavigator: true)
.pushAndRemoveUntil(
MaterialPageRoute(
builder: (BuildContext context) {
return const OnBoardingPage();
},
),
(_) => false,
);
},
icon: const Icon(Icons.logout))
I know that user's data are still there because I can display user.email in my onBoardingPage (where technically no data can be there because I logout previously).
Here a preview of my onBoardingPage :
After that, if I want to connect with another account, I will be connected to the previous user's session. The same if I want to create a new account, all new user's data will be into the previous connected user. To fix this problem, in development mode, I need to hot restart the app.
It seems like the user is not totally logout.

Related

flutter - Wait for the database to respond then navigate

I'm new to Flutter. Currently I'm trying to create a user record in the database, then switch the window.
await MemberDatabase.insertMember(member);
Navigator.pushReplacement(
context,
MaterialPageRoute(
builder: (context) => ShopKeeperPage(
email: email,
loginType: 'normal',
),
));
Before it adds data to the database, it navigates to the ShopKeeper page instantly which is causing me errors because the data is not inserted in the database yet.
Is there anyway I can make it so that it waits until the data is added in the database and then navigate to the next page?
MemberDatabase class
class MemberDatabase {
static var memberCollection;
static connect() async {
print("trying to connect");
var db = await Db.create(MONGO_CONN_URL);
await db.open();
print("Connected to the database");
memberCollection = db.collection(MEMBER_COLLECTION);
}
static insertMember(Member member) async {
return await memberCollection.insert(member.toMap());
}
}
All things equal, from the code you posted, it is waiting for insertMember. Check if insertMember is properly creating the user record as you expect.
However, for a solution. You can rewrite the code to the following. So that you are really sure that navigation is done only after creating the user record fails.
MemberDatabase.insertMember(member).then(() => Navigator.pushReplacement(
context,
MaterialPageRoute(
builder: (context) => ShopKeeperPage(
email: email,
loginType: 'normal',
),
),
));
If it doesn't work, then post more code and give more context of what you are doing. Also, check exactly the logic of MemberDatabase.insertMember, that's a place where the issue could be from. Or in the ShopKeeperPage (where Navigation is going to), it could be inappropriately accessing the created member 🤷

Consumer that checks authentication state breaks when navigating to other screens

Users of my app need to authenticate. The authentication state is tracked by a provider class. The login functionality works fine, however, users can also logout, and that is giving problems.
In main.dart I use a consumer widget to track the authentication state:
child: Consumer<AuthenticationProvider>(
builder: (ctx, auth, child) => MaterialApp(
title: 'FlutterChat',
home: auth.isAuth
? WelcomeScreen()
: FutureBuilder(
future: auth.tryAutoLogin(),
builder: (ctx, authResultSnapshot) =>
authResultSnapshot.connectionState ==
ConnectionState.waiting
? SplashScreen()
: AuthFlowScreen(),
),
),
),
At app start, the consumer will check the authentication state, if the user is not authenticated, then the user will be redirected to AuthFlowScreen, else the user will see the WelcomeScreen. If the user followed the AuthFlowScreen and successfully authenticates, the user will automatically go to the WelcomeScreen, because that is what the Consumer does.
The WelcomeScreen has a NavBar from which the user can navigate to other parts of the app. The NavBar also has a button to Logout. When this is pressed, the consumer in the main.dart file needs to react. As long as the user didn't navigate to any other screen, the logout works and the AuthFlowScreen is shown to the user. However, if the user navigated to other parts in the app, this does not happen.
Navigation happens with:
Navigator.push(context, MaterialPageRoute(builder: (context) {
return ChatOverviewScreen();
}))
Logout script:
void logout() {
_auth.signOut();
_userEmail = null;
_userId = null;
notifyListeners();
}
It seems that the navigation is messing up the consumer in the main.dart file, however, how can I navigate through the app, such that the consumer in main.dart is still working.
for login system better to use bloc state management, you can find full example here :
https://bloclibrary.dev/#/flutterlogintutorial

How reinitialize flutter MultiProvider's all providers data?

In my application, I have many providers, for instance notifications, auth, profile, conversations, trips, etc... And now I need to reinitialize all providers, when user logout. Otherwise old user data will still stay in provider, and new user will get them.
After spending my day, I solved the problem in this way. It is the most elegant way I could do. So after logout, you have to remove all screens and navigate to the root widget, within which your Provider or MultiProvider is created, and so your provider or all your providers inside MultiProvider will be recreated, and all data will be reinitialized
Navigator.of(context).pushAndRemoveUntil<T>(
MaterialPageRoute(
builder: (_) => MyApp(),
),
(_) => false,
);
Where MyApp is the root widget, which is passed as parameter in your main function in main.dart.
runApp(
MyApp(token: token),
);
You can call the providers and clear all the user's data. For example:
You can call your authProvider.logOut(), all still depends on your project structure.
RaisedButton(
child: const Text("Logout"),
onPressed: () {
final Auth auth = Provider.of<Auth>(context, listen: false);
auth.isAuthentificated = false;
},
),

Flutter-Backendless User Login __ How to Validate User Credentials (Email and Password) to move from Login Page to Home Page

Newbie mobile developer here. I'm trying to implement User Logins with Backendless but I don't know whats the best way to do it, especially to avoid making too many API calls.
I know there are several malpractices (especially UX) here but I'm really just trying to get the logic right first.
In the following excerpt, I try making a log-in and when it's done give the user access to the app. If its not successful Id like the alert to be made. However, the app shows the alert independently of the credentials being correct. It's like the if starts executing before the login has been completed.
I'm not looking for a workaround, I'm a noob developer and honestly, don't know the best way to handle this. I would be very appreciative of help. Thanks, guys!
Backendless.userService.login(email, password).then((user) => boologin=true);
if (boologin==true) {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => Home(),
),
);
} else {
showBasicAlert(context,
"Wrong username or password", "");
boologin is always false when it reaches to if. Because login is asynchronous and before boologin = true being set, code flow continues. Try to change it like here
await Backendless.userService.login(email, password);
Then to set boologin = true
As Marat said, most of the calls to the Flutter Backendless SDK is asynchronous and
you can use the await keyword to wait for a Future to complete. Or you can perform actions in the response's body.
Here is the most convenient way to handle Backendless SDK calls:
void logIn(email, password) {
Backendless.userService.login(email, password)
.then((loggedInUser) {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => Home(),
),
);
})
.catchError((onError) {
showBasicAlert(context, "Wrong username or password", "");
});
}

How to properly implement Logout with firebase on flutter

It sounds stupid but I cant really properly logout of my app and that is because I use multiple FirebaseAnimatedList and route on my MaterialApp
routes: <String,WidgetBuilder>{
'/StartAppPage':(BuildContext context)=>new StartAppPage(),
'/LoginPage':(BuildContext context)=> new LoginPage(),
'/HomePage':(BuildContext context)=> new HomePage)
},
So the app checks for use and routes to HomePage or Login based on is there is a user or not.
My Home page has a FirebaseAnimatedList and
on my Home page there is a Logout button that do this
await googleSignIn.signOut();
await FirebaseAuth.instance.signOut();
await FirebaseDatabase.instance.goOffline();
return Navigator.pushReplacementNamed(context, '/StartApp');
to HomePage and logout the user.
But when the other user login again the List shows data of the old user and the list is usable messing my Database
How can I properly implement this and the setPersistance is off or on makes no difference
Solution: Keep a single instance of your firebase user through the app. I recommend a global variable
After signing out, what you can consider doing here is check on the current screen if the user is authenticated or not. If the user is still logged-in, display the data. If not, then navigate to a Login screen.
FirebaseAuth.instance
.idTokenChanges()
.listen((User? user) {
if (user == null) {
debugPrint('User is currently signed out!');
// TODO: navigate to Login screen?
} else {
debugPrint('User is signed in!');
// TODO: display data
}
});