[英]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
}
},
)
Ans=> Use FutureBuilder or StreamBuilder Ans=> 使用 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());
},
)),
);
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.