Issue
I'm trying to find whether the logged in user is an admin or a normal user.
I have already created a global function (then called it in initState
) to check whether the role is admin or not by setting a bool to true or false as follows:
bool isAdmin;
_checkRole() async {
var firebaseUser = FirebaseAuth.instance.currentUser;
await FirebaseFirestore.instance
.collection("users")
.doc(firebaseUser.uid)
.get()
.then((value) {
if ((value.data()['role']) == 'admin') {
isAdmin = true;
} else {
isAdmin = false;
}
return isAdmin;
});
}
And here in the drawer I did the following:
isAdmin
? buildListTile(
'Admin Panel', Icons.admin_panel_settings_sharp, () {
Navigator.of(context).pushNamed(AdminScreen.routeName);
})
: buildListTile('User dashboard', Icons.person, () {}),
But when I open the drawer, I receive Failed assertion: boolean expression must not be null
Any idea on how to fix this issue?
and thank you.
Solution
Short answer:
isAdmin isn't initialized when you are building your ListTile because the async function hasn't had a chance to finish running.
Longer answer:
Your build
method happens synchronously with the rest of the code, meaning it happens one line after another. Your _checkRole()
method happens asynchronously, meaning it will get around to it whenever it gets around to it. So when you try initializing isAdmin
in your initState
method it is running a network call (which takes a long time in terms of program time) and waiting till the network call finishes to set isAdmin
. Meanwhile, your build is running and trying to build without knowing that it is supposed to wait for isAdmin
to be set.
A Solution:
(note, there are many ways to solve this, this is just one)
Use a FutureBuilder or StreamBuilder to load the variable and set the variable type to Future or the equivalent for streams and listen to the state change and build your UI accordingly.
Here's a basic example. Careful copy/pasting. I didn't run the code. This is just the general idea.
Future<bool> isAdmin;
FutureBuilder<String>(
future: Globals.isAdmin,
builder: (BuildContext context, AsyncSnapshot<Bool> snapshot) {
if (snapshot.hasData) { //
var isAdmin = snapshot.data;
// use the value for isAdmin
if (isAdmin == true) {
return Container();
} else {
return Container();
}
} else if (snapshot.hasError) {
//handle your error
return Container();
} else {
// handle your loading
return CircularProgressIndicator();
}
},
),
Answered By - developer extraordinare
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.