一尘不染

在initState中初始化一次数据,并在数据准备就绪时调用setState导致异常

flutter

由于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));

不会发生例外。


阅读 495

收藏
2020-08-13

共1个答案

一尘不染

编辑: 下面更好的答案。


显然, 您不能getData(context)在此期间访问initState(更具体:在完成之前)。

我相信,原因是getData试图InheritedWidget在树中查找祖先,但是树正在构建中(您的窗口小部件是在父窗口小部件的过程中创建的build)。

显而易见的解决方案是将getData查找延迟到以后的某个时间点。有几种方法可以实现:

  • 将查找延迟到以后的时间。scheduleMicrotask应该工作正常。
  • 在第一个build通话中查找它。您可以isInitializedfalse和中设置一个字段build,例如:
        if (!isInitialized) {
      isInitialized = true;
      // TODO: do the getData(...) stuff
    }
2020-08-13