在initState中初始化一次数据,并在数据准备就绪时调用setState导致异常
问题内容:
由于flutter在不同条件下多次调用build方法,因此为了避免多次获取数据,我在中初始化了数据initState
。
我想在数据准备好后重新构建窗口小部件。
这是我的代码:
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();
}
}
}
但是,它导致以下异常:
inheritFromWidgetOfExactType(_InheritedProvider) or inheritFromElement() was called before _TestState.initState() completed.
我可以知道我在这里做错了吗?
当我将以下行添加到getData(context)的实现中时
await Future.delayed(new Duration(milliseconds: 300));
不会发生例外。
问题答案:
编辑: 下面更好的答案。
显然, 您不能getData(context)
在此期间访问initState
(更具体:在完成之前)。
我相信,原因是getData
试图InheritedWidget
在树中查找祖先,但是树正在构建中(您的窗口小部件是在父窗口小部件的过程中创建的build
)。
显而易见的解决方案是将getData
查找延迟到以后的某个时间点。有几种方法可以实现:
- 将查找延迟到以后的时间。
scheduleMicrotask
应该工作正常。 - 在第一个
build
通话中查找它。您可以isInitialized
在false
和中设置一个字段build
,例如:
if (!isInitialized) {
isInitialized = true;
// TODO: do the getData(...) stuff
}