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.
CodePudding user response:
You have to initialise isAdmin
field with an initial value, try
bool isAdmin = false;
CodePudding user response:
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.