InitState 处于颤动状态,从 firestore 中获取文档值
InitState in flutter, deriving document value from firestore
我正在开发一个应用程序,我需要过滤掉每个登录的用户。一旦他们登录,他们将被重定向到包装器,检查用户 ID 是否存在于 Firestore 文档集合中。这是我的代码。
class adminCheck extends StatefulWidget {
const adminCheck({Key? key}) : super(key: key);
@override
State<adminCheck> createState() => _adminCheckState();
}
class _adminCheckState extends State<adminCheck> {
User? user= FirebaseAuth.instance.currentUser;
bool isAdmin=false;
void initState() {
checkIfAdmin();
super.initState();
}
@override
Widget build(BuildContext context) {
if (isAdmin==true){
countDocuments();
return HomeScreen();
}else{
return notAdmin();
}
}
void checkIfAdmin() async{
DocumentSnapshot currentUser= await FirebaseFirestore.instance.collection('Administrator')
.doc(user!.email)
.get();
if(currentUser.exists){
print("This user is admin");
setState((){
isAdmin=true;
});
}
if(!currentUser.exists){
print("This user is not an admin");
}
}
}
问题是 returnnotAdmin() class 甚至 void 方法 returns true 应该 return HomeScreen(),并且经过几次秒,它将 return HomeScreen()。我认为初始化来自 Firestore 的数据会出现延迟。请帮我解决我的问题。或者有没有办法让它在 returning 这两个 class 中的任何一个之前先等待初始化?
initState
的目的是确定小部件首次呈现时的状态。这意味着您不能在 initState
.
中使用异步信息(例如您仍需要从 Firestore 加载的数据)
如果只应在数据可用时呈现小部件,则在加载该数据之前不应呈现它。您可以通过向状态添加另一个值来指示文档正在加载来完成此操作:
class _adminCheckState extends State<adminCheck> {
User? user= FirebaseAuth.instance.currentUser;
bool isAdmin=false;
bool isLoading=true; //
然后在渲染中使用它:
@override
Widget build(BuildContext context) {
if (isLoading) { //
return CircularProgressIndicator(); //
} else if (isAdmin==true){
countDocuments();
return HomeScreen();
}else{
return notAdmin();
}
}
当然,您可以在加载数据时呈现任何您想要的内容(或者根本不加载任何内容),但 CircularProgressIndicator
通常是一个合理的默认值。
当然,最后,您需要在设置 isAdmin
时清除加载指示器:
void checkIfAdmin() async{
DocumentSnapshot currentUser= await FirebaseFirestore.instance.collection('Administrator')
.doc(user!.email)
.get();
if(currentUser.exists){
setState((){
isAdmin=true;
isLoading=false; //
});
}
if(!currentUser.exists){
print("This user is not an admin");
}
}
这种模式非常普遍,它也被封装在一个预建的小部件中。如果这听起来很吸引人,你会想看看使用 FutureBuilder
.
我正在开发一个应用程序,我需要过滤掉每个登录的用户。一旦他们登录,他们将被重定向到包装器,检查用户 ID 是否存在于 Firestore 文档集合中。这是我的代码。
class adminCheck extends StatefulWidget {
const adminCheck({Key? key}) : super(key: key);
@override
State<adminCheck> createState() => _adminCheckState();
}
class _adminCheckState extends State<adminCheck> {
User? user= FirebaseAuth.instance.currentUser;
bool isAdmin=false;
void initState() {
checkIfAdmin();
super.initState();
}
@override
Widget build(BuildContext context) {
if (isAdmin==true){
countDocuments();
return HomeScreen();
}else{
return notAdmin();
}
}
void checkIfAdmin() async{
DocumentSnapshot currentUser= await FirebaseFirestore.instance.collection('Administrator')
.doc(user!.email)
.get();
if(currentUser.exists){
print("This user is admin");
setState((){
isAdmin=true;
});
}
if(!currentUser.exists){
print("This user is not an admin");
}
}
}
问题是 returnnotAdmin() class 甚至 void 方法 returns true 应该 return HomeScreen(),并且经过几次秒,它将 return HomeScreen()。我认为初始化来自 Firestore 的数据会出现延迟。请帮我解决我的问题。或者有没有办法让它在 returning 这两个 class 中的任何一个之前先等待初始化?
initState
的目的是确定小部件首次呈现时的状态。这意味着您不能在 initState
.
如果只应在数据可用时呈现小部件,则在加载该数据之前不应呈现它。您可以通过向状态添加另一个值来指示文档正在加载来完成此操作:
class _adminCheckState extends State<adminCheck> {
User? user= FirebaseAuth.instance.currentUser;
bool isAdmin=false;
bool isLoading=true; //
然后在渲染中使用它:
@override
Widget build(BuildContext context) {
if (isLoading) { //
return CircularProgressIndicator(); //
} else if (isAdmin==true){
countDocuments();
return HomeScreen();
}else{
return notAdmin();
}
}
当然,您可以在加载数据时呈现任何您想要的内容(或者根本不加载任何内容),但 CircularProgressIndicator
通常是一个合理的默认值。
当然,最后,您需要在设置 isAdmin
时清除加载指示器:
void checkIfAdmin() async{
DocumentSnapshot currentUser= await FirebaseFirestore.instance.collection('Administrator')
.doc(user!.email)
.get();
if(currentUser.exists){
setState((){
isAdmin=true;
isLoading=false; //
});
}
if(!currentUser.exists){
print("This user is not an admin");
}
}
这种模式非常普遍,它也被封装在一个预建的小部件中。如果这听起来很吸引人,你会想看看使用 FutureBuilder
.