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

ulmd4ohb  于 2023-01-18  发布在  Flutter
关注(0)|答案(3)|浏览(233)

在我的main.dart文件中,我想检查用户是否已登录,以便将他引导到适当的屏幕。我正在使用SharedPreference存储来自Firebase的用户详细信息。如何告诉我的函数等待SharedPreference异步函数完成执行,然后才能呈现适当的小部件。
下面是我的代码:

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

}

xxe27gdn

xxe27gdn1#

你不必等待构建,你应该构建一些东西,向用户显示应用程序正在加载一些东西(或黑屏),然后在功能结束时重建。
您可以在创建小部件时将一个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());
      }
    });
  }
}

另一种方法是使用一个变量来通知你加载的情况,比如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; });
  });
}
dhxwm5r4

dhxwm5r42#

使用简单的FutureBuilder!
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
  }
 },
)
mwngjboj

mwngjboj3#

有一个异步firebase函数吗?

回答=〉使用FutureBuilder或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());
          },
        ),
      ),
    );
  }
未来建筑师
@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());
        },
      )),
    );
  }

相关问题