【发布时间】:2018-09-11 20:26:33
【问题描述】:
更新:已解决,请看下面的答案。
我有一个简单的文本(初始文本值为“空”)小部件和屏幕顶部的一个按钮。当我单击按钮时,我正在加载一个需要很长时间才能完成的文件。在完成该任务的同时,我想将 Text 小部件更改为“正在加载”,然后在该任务完成加载文件后显示文件的内容。
我在 Future 和 State 类的构建函数中运行加载任务,我使用 FutureBuilder 小部件根据任务是否完成来了解 Text 小部件应显示的内容。
我认为问题在于,因为 dart 是一个单线程应用程序,将 Text 小部件的文本更改为“正在加载”不会仅在任务完成后执行,这超出了目的(即使当调用 setState,因为它被添加到事件循环中,我相信 Future 也计划在其中运行)。
我应该在单独的 Isolate 中运行长任务吗?这是正确的方法吗?搞这个很久了,希望有人能帮忙,应该就是这么简单..
这是我正在使用的代码:
void main() => runApp(new MyApp());
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return new MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Flutter Demo',
home: new MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key}) : super(key: key);
@override
_MyHomePageState createState() => new _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
String content = 'Empty';
Future<FileObject> file;
loadData() async {
// do the loading of the file here (that takes a LONG time)
file = /*loadfunction for the file (returns a Future, because it takes long)*/;
}
loadTask() {
setState(() {
content = 'Loading...';
});
loadData();
}
@override
Widget build(BuildContext context) {
return new Scaffold(
backgroundColor: Colors.black,
body: Column(
children: <Widget>[
buildTitle(),
buildContent(),
],
),
);
}
FutureBuilder<FileObject> buildContent() {
return FutureBuilder<FileObject>(
future: file,
builder: (BuildContext context, AsyncSnapshot<FileObject> snapshot) {
if (snapshot.hasData) {
content = snapshot.data.text; // The FileObject has a text property
}
return Expanded(
child: SingleChildScrollView(
child: Text(
content,
textAlign: TextAlign.center,
style: TextStyle(
color: Colors.lightBlue[100],
fontSize: 25.0,
fontWeight: FontWeight.normal,
),
),
),
);
},
);
}
Padding buildTitle() {
return Padding(
padding: const EdgeInsets.only(left: 8.0, top: 50.0, bottom: 30.0),
child: Row(
children: <Widget>[
IconButton(
icon: Icon(
Icons.update,
color: Colors.lightBlue[50],
),
onPressed: loadTask,
),
],
),
);
}
}
【问题讨论】:
-
你的
loadContent函数没用。您可以直接访问snapshot.data中的文件值 :) -
我实际上只是现在更改了它,并按照您的建议将该 loadContent 活动移动到 FutureBuilder 部分(当然不需要 setState,并使用 if snapshot.hasData 而不是检查连接状态),但是仍然没有改变任何东西......太奇怪了
-
你能更新你的代码吗?
-
当然,现在应该更新
-
为什么不放弃 FutureBuilder 并在文件加载时再次调用 setState?