在initState中初始化一次数据,并在数据准备就绪时调用setState导致异常 [英] initialize data once in initState and call the setState when data is ready causes exception

查看:302
本文介绍了在initState中初始化一次数据,并在数据准备就绪时调用setState导致异常的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

由于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 an isInitialized field set to false and in you build, something like:

if (!isInitialized) {
  isInitialized = true;
  // TODO: do the getData(...) stuff
}

这篇关于在initState中初始化一次数据,并在数据准备就绪时调用setState导致异常的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆