我想阅读一些txt并将其文本存储在数组中。但是因为我的GUI需要这个数组,所以应该等到所有操作完成。
Future<String> getFileData(String path) async {
return await rootBundle.loadString(path);
}
int topicNr = 3;
int finished = 0;
for (int topic = 1; topic <= topicNr; topic++) {
getFileData('assets/topic' + topic.toString() + '.txt').then(
(text) {
topics.add(text);
},
).whenComplete(() {
finished++;
});
}
while (finished < topicNr)
但是当我运行这段代码时,finish不会更新(我认为是因为while循环在主线程上运行,因此异步功能不能同时运行)
我可以通过等待来做到这一点,但这并不是一个好的解决方案:
Future.delayed(const Duration(milliseconds: 10), () {
runApp(MaterialApp(
title: 'Navigation Basics',
home: MainMenu(),
));
});
我现在如何才能等到所有这些异步功能完成?
(对不起,我是Flutter的新手)
答案 0 :(得分:0)
您可以做的一件事是使用有状态的小部件和加载模式。页面初始化后,将视图设置为加载模式,然后调用获取数据并使用set状态填充数据的函数。完成/确定最终数据已加载后,将加载设置为false。请参见下面的示例:
{1: {}, 2: {}, 3: {}, 4: {}, 5: {}}
您还可以将初始数据的字段设置为空值,并使用set状态在获取数据时为其提供实际值。 例如
class Page extends StatefulWidget {
page();
@override
State<StatefulWidget> createState() => new _Page();
}
class _Page extends State<Page>{
bool _loading = true; //used to show if the page is loading or not
@override
void initState() {
getFileData(path); //Call the method to get the data
super.initState();
}
Future<String> getFileData(String path) async {
return await rootBundle.loadString(path).then((onValue){
setState(() { //Call the data and then set loading to false when you are done
data = on value.data;
_loading = false;
});
})
}
//You could also use this widget if you want the loading modal ontop your page.
Widget IsloadingWidget() {
if (_loading) {
return Stack(
children: [
new Opacity(
opacity: 0.3,
child: const ModalBarrier(
dismissible: false,
color: Colors.grey,
),
),
new Center(
child: new CircularProgressIndicator(
valueColor:
new AlwaysStoppedAnimation<Color>(Colors.green),
strokeWidth: 4.0,
),
),
],
);
} else {
return Container();
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Stack(
children: <Widget>[
//If loading, return a loading widget, else return the page.
_loading ?
Container(
child: Center(
child: CircularProgressIndicator(
valueColor: new AlwaysStoppedAnimation<Color>(
Colors.blue))))
:Column(
children:<Widget>[
//Rest of your page.
]
)
]))
}
}
让我知道是否有帮助。
答案 1 :(得分:0)
使用FutureBuilder
等待API调用完成,然后再构建widget
。
请参见以下示例:https://flutter.dev/docs/cookbook/networking/fetch-data
runApp(MaterialApp(
title: 'Navigation Basics',
home: FutureBuilder(
future: getFileData(),
builder: (context, snapshot) {
if (snapshot.hasData) {
return MainMenu()
} else {
return CircularProgressIndicator();
}
));