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.