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

时间:2018-10-16 06:01:50

标签: 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();
    }
  }

}

但是,它导致以下异常: _TestState.initState()完成之前,调用了InheritFromWidgetOfExactType(_InheritedProvider)或InheritFromElement()。

我可以知道我在这里做错了吗?

当我将以下行添加到getData(context)的实现中

     await Future.delayed(new Duration(milliseconds: 300));

,不会发生异常。

谢谢!

4 个答案:

答案 0 :(得分:2)

我将代码从initState移到了build方法,并且有效

public ActionResult Details(int? id)
        {
            if (id == null)
            {
                return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
            }
            Order order = db.Orders.Find(id);
            if (order == null)
            {
                return HttpNotFound();
            }
            return View(order);
        }

答案 1 :(得分:2)

另一种选择是将其放在<div class="border" style="width: 200px; height:200px"> <div class="mx-auto my-auto border" style="width:20px; height:20px"></div> </div> PostFrameCallback之间的initState内。

Build

答案 2 :(得分:1)

显然,您无法在getData(context) 期间访问initState(更具体的说:在完成之前)。

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

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

  • 将查询延迟固定的时间。将Future.delayedDuration.zero配合使用会很好。
  • 在第一个build调用期间进行查找。您可以将isInitialized字段设置为false,在您的build中,类似以下内容:

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

答案 3 :(得分:1)

以后再来的人

最好使用@override void didChangeDependencies ()类的State方法。

docs

  

在initState之后也立即调用此方法。从此方法调用BuildContext.inheritFromWidgetOfExactType是安全的。

但是请确保检查您是否已经执行了初始化

@override
void didChangeDependencies() {
  super.didChangeDependencies();
  if (bloc == null) { // or else you end up creating multiple instances in this case.
    bloc = BlocProvider<MyBloc>.of(context);
  }
}