After the first Log In in my App I want to fetch the userdata with a Futurebuilder. Therefore I want to fetch the data from firestore and store the values in a static Helper class:
/// Helper Class
class UserManager {
static Map<String, dynamic> userdata = null;
}
class FireBaseHandler {
final CollectionReference usersCol = FirebaseFirestore.instance.collection(
'users');
final myUser = FirebaseAuth.instance.currentUser;
/// fetch UserData
Future getUserData() async {
try {
await usersCol
.doc(myUser.uid)
.get().then((value) => UserManager.userdata = value.data());
return UserManager.userdata;
} catch (e) {
print(e.toString());
}
}
}
/// Futurebuilder in main Code
FireBaseHandler handler = FireBaseHandler();
return FutureBuilder(
future: handler.getUserData(), /// get userData and store it in Helper class
builder: (context, userDataSnapshot) {
if (userDataSnapshot.hasData) {
print(UserManager.userdata);
return HomeScreen();
} else {
return Scaffold(
body: Center(
child: CircularProgressIndicator(),
),
);
}
});
The Problem is that the snapshot from the Futurebuilder never has Data so userDataSnapshot.hasData
is never true and it stays in loading Screen. Only when I hot reload the snapshot has Data and I go to the homescreen. Whats the Problem?
CodePudding user response:
Don't mix async
/ await
and .then
, they both do the same but the two syntaxes can't be mixed. Also set the appropriate data type for your Future
function and return the result of database fetch. You don't really need try/catch
, you will handle errors in the FutureBuilder
:
Future<Map<String, dynamic>> getUserData() async {
return await usersCol.doc(myUser.uid).get();
}
return FutureBuilder(
future: handler.getUserData(), /// get userData and store it in Helper class
builder: (context, userDataSnapshot) {
if (userDataSnapshot.hasError) {
return const Text('Error');
}
if (userDataSnapshot.hasData) {
if (!snapshot.data!.exists) {
return const Text('Document not found');
}
else {
UserManager.userdata = userDataSnapshot.data!.data();
print(UserManager.userdata);
return HomeScreen();
}
}
// still loading
else {
return Scaffold(
body: Center(
child: CircularProgressIndicator(),
),
);
}
});
CodePudding user response:
I think the problem is the way you initialize UserManager.userdata
in a lambda function inside the then (() {...})
this initialization is local to this function, reason why UserManager.userdata
remains null
try to do as in the example below :
Future getUserData() async {
UserManager.userdata = (await usersCol.doc(myUser.uid).get()).data();
return UserManager.userdata;
}
I think the value of UserManager.userdata
will be available only in getUserData()
if you want to use UserManager.userdata
in another class, I guess it will be null,
Good way below, your function got just to return
Future<Map<String, dynamic>> getUserData() async {
return (await usersCol.doc(myUser.uid).get()).data();
}