在initState中初始化一次数据,并在数据准备就绪时调用setState导致异常 [英] initialize data once in initState and call the setState when data is ready causes exception
问题描述
由于flutter在不同条件下多次调用了build方法,为避免多次获取数据,我在initState
中初始化了数据.
Since flutter calls the build method many times in different condition, to avoid getting the data many times, I initialize the data in initState
.
我想在数据准备好后重新构建窗口小部件.
I want to re-build the widget when the data is ready.
这是我的代码:
class Test extends StatefulWidget {
@override
_TestState createState() => new _TestState();
}
class _TestState extends State<Test> {
Data data;
bool dataReady = false;
@override
void initState() {
super.initState();
getData(context).then((Data data) async {
setState(() {
dataReady= true;
});
});
}
@override
Widget build(BuildContext context) {
if (dataReady) {
return createMainContent(context);
} else {
return new Container();
}
}
}
但是,它导致以下异常:
However, it results in following exception :
inheritFromWidgetOfExactType(_InheritedProvider) or inheritFromElement() was called before _TestState.initState() completed.
我可以知道我在这里做错了吗?
May I know am I doing something wrong here?
当我将以下行添加到getData(context)的实现中
When I add the following line to implementation of getData(context)
await Future.delayed(new Duration(milliseconds: 300));
该异常不会发生.
推荐答案
编辑:下面是更好的答案.
Better answer below.
显然,您不能在initState
期间访问getData(context)
(更具体的说:在完成之前).
Apparently, you cannot access getData(context)
during initState
(more concrete: before it completed).
我相信原因是getData
试图在树中向上查找InheritedWidget
祖先,但是树正在构建(您的窗口小部件是在父窗口小部件的build
期间创建的)
The reason, so I believe, is that getData
tries to look up an InheritedWidget
ancestor up in the tree, but the tree is just now being built (your widget is created during the parent widget's build
).
显而易见的解决方案是将getData
的查找延迟到以后的某个时间点.有几种方法可以实现这一目标:
The obvious solution would be to delay getData
's lookup to a later point in time. There are several ways to achieve that:
- 将查找延迟到以后.
scheduleMicrotask
应该可以正常工作. -
在第一个
build
调用期间查找它.您可以将isInitialized
字段设置为false
,在您的build
中,类似以下内容:
- Delay the lookup to a later time.
scheduleMicrotask
should work fine. Look it up during the first
build
call. You could have anisInitialized
field set tofalse
and in youbuild
, something like:
if (!isInitialized) {
isInitialized = true;
// TODO: do the getData(...) stuff
}
这篇关于在initState中初始化一次数据,并在数据准备就绪时调用setState导致异常的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!