简体   繁体   English

在 Flutter 中呈现小部件之前,如何等待异步 function 完成执行

[英]How do I wait for an async function to finish executing before rendering a widget in Flutter

On my main.dart file, I want to check if a user is logged so as to direct him to the appropriate screen.在我的main.dart文件中,我想检查用户是否已登录以便将他定向到适当的屏幕。 I am using SharedPrefence to store user detail from Firebase. How do I tell my function to wait until my SharedPreference async function finishes executing before it can render the appropriate widget.我正在使用 SharedPrefence 存储来自 Firebase 的用户详细信息。如何告诉我的 function 等到我的 SharedPreference 异步 function 完成执行才能呈现适当的小部件。

Below is my code:下面是我的代码:

  Widget _gotoHomeScreen() {
  AuthService.getuserPrefEmail().then((email) {
  print(email);
  AuthService.email = email;
  if (email == null) {
    return LoginScreen();
  } else {
    AuthService.uid = email;
    return HomeMenuScreen();
  }
});

} }

You don't have to wait for the build, you should build something, to show to the user that the app is loading something (or a blank screen), and then rebuild when the funcion ends.您不必等待构建,您应该构建一些东西,向用户显示应用程序正在加载某些东西(或空白屏幕),然后在功能结束时重建。

You could have a Widget variable that is set to a default when you create the widget, say with a CircularProgressIndicator , then change it with setState, something like this:您可以在创建小部件时将 Widget 变量设置为默认值,例如使用CircularProgressIndicator ,然后使用 setState 更改它,如下所示:

class YourWidgetState extends State<YourWidget> {
  Widget _body = CircularProgressIndicator();  // Default Body

  @override
  void initState(){
    _gotoHomeScreen();
  }

  @override
  Widget build(BuildContext context){
    return _body;
  }

  Widget _gotoHomeScreen() {
    AuthService.getuserPrefEmail().then((email){
      AuthService.email = email;
      if (email == null) {
        setState(() => _body = LoginScreen());
      } else {
        AuthService.uid = email;
        setState(() => _body = HomeMenuScreen());
      }
    });
  }
}

Another way would be to use a variable to inform you about the loading situation, like bool finishedLoading , and call setState to change the value when it's done, using the email variable you set to know when the user is logged in, and do a conditional build, like this:另一种方法是使用变量通知您加载情况,例如bool finishedLoading ,并在完成后调用setState更改值,使用您设置的email变量来了解用户何时登录,并执行条件构建,像这样:

bool loading = true;

@override
Widget build(BuildContext context){
  if(loading) return CircularProgressIndicator();

  if(AuthService.email == null)
    return LoginScreen();
  else
    return HomeMenuScreen();
}

Widget _gotoHomeScreen() {
  AuthService.getuserPrefEmail().then((email){
    AuthService.email = email;
    if (email != null) {
     AuthService.uid = email;
    }
    setState((){ loading = false; });
  });
}

Use a simple FutureBuilder!使用一个简单的 FutureBuilder!

https://api.flutter.dev/flutter/widgets/FutureBuilder-class.html https://api.flutter.dev/flutter/widgets/FutureBuilder-class.html

FutureBuilder<Email>(
future: AuthService.getuserPrefEmail(),
 builder: (BuildContext context, AsyncSnapshot<String> snapshot) {
  switch (snapshot.connectionState) {
    case ConnectionState.active:
    case ConnectionState.waiting:
     return CircularProgressIndicator();
    case ConnectionState.done:
     if (snapshot.hasError) {
       return Text('Error: ${snapshot.error}');
      }
     .... here route to your screen or set it how you want
  }
 },
)

Have a async firebase function?有异步 firebase function 吗?

Ans=> Use FutureBuilder or StreamBuilder Ans=> 使用 FutureBuilder 或 StreamBuilder


StreamBuilder StreamBuilder

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: StreamBuilder<QuerySnapshot>(
          stream: FirebaseFirestore
                  .instance.
                  .collection('users') // 👈 Your desired collection name here
                  .snapshots(), 
          builder: (BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot) {
            if (snapshot.hasError) {
              return const Text('Something went wrong');
            }
            if (snapshot.connectionState == ConnectionState.waiting) {
              return const Text("Loading");
            }
            return ListView(
                children: snapshot.data!.docs.map((DocumentSnapshot document) {
              Map<String, dynamic> data =
                  document.data()! as Map<String, dynamic>;
              return ListTile(
                title: Text(data['fullName']), // 👈 Your valid data here
              );
            }).toList());
          },
        ),
      ),
    );
  }

FutureBuilder未来建造者

@override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
          child: FutureBuilder<QuerySnapshot>(
        future: FirebaseFirestore
                .instance
                .collection('users') // 👈 Your collection name here
                .get(), 
        builder: (_, snapshot) {
          if (snapshot.hasError) return Text('Error = ${snapshot.error}');
          if (snapshot.connectionState == ConnectionState.waiting) {
            return const Text("Loading");
          }
          return ListView(
              children: snapshot.data!.docs.map((DocumentSnapshot document) {
            Map<String, dynamic> data = document.data()! as Map<String, dynamic>;
            return ListTile(
              title: Text(data['avatar']), // 👈 Your valid data here
            );
          }).toList());
        },
      )),
    );
  }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何在执行任务之前等待多个 firebase 查询完成? - How to wait for multiple firebase queries to finish before executing a task? 在返回所有异步函数以更新 firestore 文档之前,如何等待 NodeJS 中的多个异步函数? - How do I wait for multiple async functions in NodeJS before returning them all to update a firestore document? 如何在运行另一个之前等待异步 function - How to wait for a async function before run the other one 如何在继续之前等待 getDownloadURL 完成? - How to wait for getDownloadURL to finish before proceeding? 如何等待数据可用 - flutter - How can I wait for data before it is available - flutter Flutter:当小部件没有父/子关系时,如何从小部件 B 调用小部件 A 中的 function? - Flutter: How do I call a function in widget A from widget B when the widgets do not have a parent/child relationship? Flutter 在加载 Widget 之前调用 Firebase Function - Flutter call Firebase Function before loading Widget 如何让我的程序在执行 function 之前等待 Firebase 的数据? - How can make my Program wait for Firebase's data before executing a function? 如何调用 function 但不要等待完成 - ASP.NET - How to invoke a function but don't wait to finish - ASP.NET 在返回之前等待完成处理程序完成 - Wait for completion handler to finish before returning
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM