当前位置: 首页 > 面试题库 >

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

萧业
2023-03-14
问题内容

由于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通话中查找它。您可以isInitializedfalse和中设置一个字段build,例如:
        if (!isInitialized) {
      isInitialized = true;
      // TODO: do the getData(...) stuff
    }


 类似资料:
  • 初始化数据 打开MainSetup类,在Daos语句后面插入新建根用户的代码 // 初始化默认根用户 if (dao.count(User.class) == 0) { User user = new User(); user.setName("admin"); user.setPassword

  • 问题内容: 我正在运行一个dockerized mongo容器。 我想用一些初始化的数据创建一个mongo图像。 有任何想法吗? 问题答案: 首先创建一个docker卷 然后创建您的mongo容器 在这里交换机负责安装的卷在的位置,这是在蒙戈保存其数据。该卷是持久的(在主机上)。即使没有容器在运行,您也会看到mongostore的卷列出为 您可以杀死该容器并创建一个新容器(与上述相同),新的mon

  • 我遇到了一个问题: 获取健康检查以成功。尝试使用容器本机负载平衡(CNLB)时,在IIS容器中运行的Net app。 我有一个网络endpoint组(NEG),由GKE中的入口资源定义和VPC本机集群创建。 当我通过公开NodePort或制作LoadBalancer类型的服务来规避CNLB时,站点会毫无问题地解决。 所有的吊舱条件从一个描述看起来不错:吊舱准备就绪 运行时会显示网络endpoint

  • 问题内容: 好的,这可能只是一个愚蠢的问题,尽管我敢肯定会有很多其他人不时问同样的问题。我,我只是想以任何一种方式100%确定它。有了jQuery,我们都知道精彩之处 但是,假设我要运行一个用标准JavaScript编写且没有库支持的函数,并且我想在页面准备就绪后立即启动一个函数。解决这个问题的正确方法是什么? 我知道我可以做: …或者我可以使用标记: …或者我什至可以尝试在页面底部输入所有内容,

  • 问题内容: 我想在Web应用程序启动时加载属性文件并设置连接池。显然,我只想在一个地方进行一次,因此可以根据需要进行更改。对于常规的servlet,我只需将初始化代码放在servlet的init()方法中,但是您无法使用Jersey servlet对其进行访问。那么我在哪里做呢?上面链接中的侦听器如何工作? 问题答案: 您需要做的就是编写一个实现ServletContextListener接口的J

  • 我有一个标准的JavaFX应用程序,可以扩展应用程序。我展示的第一个页面是一个仪表板,上面有打开其他应用程序的按钮。这很好,第一个应用程序是一个名为AdminController的管理页面,允许用户对模型对象(用户、联系人、产品)进行CRUD操作。每个实体都是管理视图上的一个选项卡。因此,在我的主管理FXML(使用SceneBuilder)中,我使用fx包括其他FXML页面:包括用户选项卡、联系人

  • 我有一个AngularJS服务,我想用一些异步数据初始化它。类似这样的事情: 显然,这是行不通的,因为如果在返回之前,有东西试图调用,我将得到一个空指针异常。据我所知,从这里和这里所问的其他一些问题中,我有几个选择,但没有一个看起来很清楚(也许我遗漏了什么): 使用“运行”设置服务 设置应用程序时,请执行以下操作: 那么我的服务将如下所示: 这在某些时候起作用,但如果异步数据的时间恰好比初始化所有

  • 问题内容: 我有一个AngularJS服务,我想使用一些异步数据进行初始化。像这样: 显然,这是行不通的,因为如果在返回之前尝试进行调用,我将得到一个空指针异常。据我从阅读这里和这里提出的其他一些问题中所知道的,我有一些选择,但是它们似乎都不是很干净(也许我错过了一些东西): 安装服务“运行” 设置我的应用程序时,请执行以下操作: 然后我的服务将如下所示: 这有时会起作用,但是如果异步数据恰好比初