【问题标题】:How to wait for async in initState如何在 initState 中等待异步
【发布时间】:2020-03-20 20:12:00
【问题描述】:

我有一个异步函数,需要在有状态小部件的 initState 中调用,但我不能使用 await,因为 initState 不是异步的。

sendHealthData 是async,因为它从 Health Api 获取一些信息,然后我需要将该信息发送到另一个 StatefulWidget 的 HomeSubScreen。但是在创建 HomeSubScreen 时,sendHealthData 方法并没有获取所有信息,所以如果我尝试将参数中的一些值发送到 HomeSubScreen,则该值将为 null。

我该怎么做?

@override
  void initState() {
    super.initState();
    sendHealthData();
    _widgetOptions = <Widget>[
      HomeSubScreen(healthData),
    ];

  }

更新: 如果我添加了 then() 我会收到以下错误:

NoSuchMethodError: The method 'elementAt' was called on null.

代码更新:

@override
      void initState() {
        super.initState();
        sendHealthData().then((response){
             _widgetOptions = <Widget>[
                 HomeSubScreen(healthData),
              ];
        });


      }

【问题讨论】:

标签: flutter


【解决方案1】:

我给你一个大致的概念。

@override
void initState() {
  super.initState();

  function().then((int value) {
    // future is completed you can perform your task 
  });

  function2(); // or you can simply call the method if you don't want anything to do after future completes
}

Future<int> function() async {
  // do something here 
}

Future<int> function2() async {
  // do something here
}

【讨论】:

  • 我认为setState(() {); 应该在function().then((int value) { // future is completed you can perform your task }); 内部,以便在获取结果后更改状态。
  • 是的,你没看错,如果你想反映UI的变化,你可以把setState放进去。我只是想说明如何处理它。
  • 但是我需要更新的值在其他StatefulWidget中。 setState 对此有用吗?
【解决方案2】:

您不能在 initState 中等待异步函数,但有一个小技巧是使用 Then 关键字在未来完成后执行代码。

例如:

@override


void initState() {
    super.initState();
    sendHealthData().then((response){

      _widgetOptions = <Widget>[
        HomeSubScreen(response),
      ];

    });


  }

而且函数必须是这样的:

Future sendHealthData() async{}

【讨论】:

  • 当我应用此解决方案时,我收到一条错误消息:NoSuchMethodError: The method 'elementAt' was called on null。仅当我将 _widgetOptions 放在 then 函数中时才会发生这种情况
  • 很抱歉,没有完整的代码,很难解决这个错误!可以发一下吗?
【解决方案3】:

你也可以使用FutureBuilder

FutureBuilder<String>(
  future: getYourDataFromApi(), 
  builder: (BuildContext context, AsyncSnapshot<String> snapshot) {
    switch (snapshot.connectionState) {
      case ConnectionState.none:
        return Text('start widget');
      case ConnectionState.active:
      case ConnectionState.waiting:
        return Text('Awaiting result from api...');
      case ConnectionState.done:
        if (snapshot.hasError)
          return Text('Error: ${snapshot.error}');
        return Text('Result: ${snapshot.data}');
    }
    return null; // unreachable
  },
)

【讨论】:

  • 这是惯用的答案。实际上,您将需要等待的小部件(可以是 MaterialApp 或任何其他小部件)包装在一个类中,该类将等待您的 async 工作完成,然后返回您喜欢的任何小部件,可选择使用 @ 987654325@ 在case ConnectionState.done: 中的返回值。您在future: 属性中指定的函数调用可以通过任何async 函数执行您需要做的任何工作(可能是使用await 等的一堆东西)。无论该函数返回什么,您都可以通过snapshot.data 获得。
猜你喜欢
  • 2020-07-28
  • 2021-07-25
  • 2021-10-22
  • 1970-01-01
  • 2014-09-06
  • 2020-07-11
  • 1970-01-01
  • 2023-03-12
  • 2020-07-10
相关资源
最近更新 更多