获取异步函数的 NULL 值(使用等待之后),然后更新为新值

2024-04-04

当我运行我的应用程序时,它会抛出很多错误,并且我的设备上会出现红色/黄色错误屏幕,它会自动刷新并向我显示预期的输出。

从日志中我可以看到,首先我的对象返回为 null,随后以某种方式更新并获得输出。

我最近开始了 Android 开发(Flutter)

我尝试遵循一些在线指南,并阅读有关异步响应的相关问题,但没有任何故障排除对我有帮助。 我最大的问题是我无法弄清楚问题到底是什么。

在我的 _AppState 类中:

  void initState() {
    super.initState();
    fetchData();
  }

  fetchData() async {
    var cityUrl = "http://ip-api.com/json/";
    var cityRes = await http.get(cityUrl);
    var cityDecodedJson = jsonDecode(cityRes.body);
    weatherCity = WeatherCity.fromJson(cityDecodedJson);
    print(weatherCity.city);
    var weatherUrl = "https://api.openweathermap.org/data/2.5/weather?q=" +
        weatherCity.city +
        "," +
        weatherCity.countryCode +
        "&appid=" +
        //Calling open weather map's API key from apikey.dart
        weatherKey;
    var res = await http.get(weatherUrl);
    var decodedJson = jsonDecode(res.body);
    weatherData = WeatherData.fromJson(decodedJson);
    print(weatherData.weather[0].main);
    setState(() {});
  }

预期输出(终端):

Mumbai
Rain

实际输出(终端):https://gist.github.com/Purukitto/99ffe63666471e2bf1705cb357c2ea32 https://gist.github.com/Purukitto/99ffe63666471e2bf1705cb357c2ea32(实际错误超出了 StackOverflow 的正文限制)

ScreenShots: At run initial After a few seconds


The async and await是 Dart 中处理异步编程的机制。

异步操作让您的程序在等待时完成工作 以便完成另一项操作。

所以每当一个方法被标记为async,您的程序不会因该方法的完成而暂停,只是假设它将在将来的某个时刻完成。

示例:错误地使用异步函数

下面的例子展示了异步函数的错误使用方式getUserOrder().

String createOrderMessage () {
  var order = getUserOrder(); 
  return 'Your order is: $order';
}

Future<String> getUserOrder() {
  // Imagine that this function is more complex and slow
  return Future.delayed(Duration(seconds: 4), () => 'Large Latte'); 
}

main () {
  print(createOrderMessage());
}

如果运行上面的程序,它将产生以下输出 -

Your order is: Instance of '_Future<String>'

这是因为,由于该方法的返回类型被标记为Future https://api.dart.dev/stable/2.4.1/dart-async/Future-class.html,程序会将 is 视为异步方法。

为了获取用户的订单,createOrderMessage()应该打电话getUserOrder()并等待它完成。因为createOrderMessage()不等待getUserOrder()完成,createOrderMessage()无法获取字符串值getUserOrder()最终提供。


异步和等待

async 和await 关键字提供了一种声明性方式来定义异步函数并使用其结果。

所以每当你声明一个函数时async,您可以使用关键字await在任何方法调用之前,这将迫使程序在该方法完成之前不再继续进行。


例证

就你而言,fetchData()函数被标记为async你正在使用await等待网络调用完成。

但在这儿fetchData()返回类型为Future<void>因此当你调用里面的方法时initState()你必须这样做而不使用async/ await since initState()无法标记async.

所以程序不会等待完成fetchData()方法作为一个整体并试图显示本质上是null。 自从你打电话以来setState()数据加载到里面之后fetchData(),屏幕刷新,一段时间后即可看到详细信息。

因此出现红色和黄色屏幕错误。


Solution

此问题的解决方案是您可以在屏幕上显示加载指示器,直到数据完全加载。

您可以使用bool变量并根据该变量的值更改 UI。

例子 -

class _MyHomePageState extends State<MyHomePage> {
  bool isLoading = false;

  void initState() {
    super.initState();
    fetchData();
 }

 fetchData() async {
   setState(() {
     isLoading = true; //Data is loading
   });
   var cityUrl = "http://ip-api.com/json/";
   var cityRes = await http.get(cityUrl);
   var cityDecodedJson = jsonDecode(cityRes.body);
   weatherCity = WeatherCity.fromJson(cityDecodedJson);
   print(weatherCity.city);
   var weatherUrl = "https://api.openweathermap.org/data/2.5/weather?q=" + weatherCity.city + "," +
    weatherCity.countryCode +
    "&appid=" +
    //Calling open weather map's API key from apikey.dart
    weatherKey;
    var res = await http.get(weatherUrl);
    var decodedJson = jsonDecode(res.body);
    weatherData = WeatherData.fromJson(decodedJson);
    print(weatherData.weather[0].main);
    setState(() {
      isLoading = false; //Data has loaded
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: isLoading ? Center(child : CircularProgressIndicator())
      : Container(), //Replace this line with your actual UI code
    );
  }
}

希望这可以帮助!

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

获取异步函数的 NULL 值(使用等待之后),然后更新为新值 的相关文章

随机推荐