Pur*_*tto 5 android future async-await dart flutter
当我运行我的应用程序时,它会抛出很多错误,我的设备上会出现红色/黄色错误屏幕,它会自动刷新并向我显示预期的输出。
从日志中我可以看到,首先我的对象返回为空,稍后以某种方式更新并获得输出。
我最近开始了 Android Dev (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(() {});
}
Run Code Online (Sandbox Code Playgroud)
预期输出(终端):
Mumbai
Rain
Run Code Online (Sandbox Code Playgroud)
实际输出(终端):https : //gist.github.com/Purukitto/99ffe63666471e2bf1705cb357c2ea32(实际错误是越过StackOverflow的body limit)
该async和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());
}
Run Code Online (Sandbox Code Playgroud)
如果您运行上述程序,它将产生以下输出 -
Your order is: Instance of '_Future<String>'
Run Code Online (Sandbox Code Playgroud)
这是因为,由于方法的返回类型被标记为Future,程序会将 is 视为异步方法。
要获取用户的订单,createOrderMessage()应该调用getUserOrder()并等待它完成。因为createOrderMessage()不等待getUserOrder()完成,createOrderMessage()未能得到getUserOrder()最终提供的字符串值。
异步和等待
async 和 await 关键字提供了一种声明方式来定义异步函数并使用它们的结果。
因此,无论何时将函数声明为async,都可以await在任何方法调用之前使用关键字,这将强制程序在方法完成之前不会继续进行。
案例
在您的情况下,该fetchData()函数被标记为async并且您正在使用它await来等待网络调用完成。
但是这里fetchData()有一个返回类型,Future<void>因此当你调用内部的方法时,initState()你必须这样做而不使用async/ await因为initState()无法标记async。
因此,程序不会等待fetchData()整个方法完成,而是尝试显示本质上是null. 并且由于您setState()在内部加载数据后调用fetchData(),因此屏幕会刷新,您可以在一段时间后看到详细信息。
因此出现红色和黄色屏幕错误。
解决方案
解决这个问题的方法是你可以在屏幕上显示一个加载指示器,直到数据加载完成。
您可以使用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
);
}
}
Run Code Online (Sandbox Code Playgroud)
希望这可以帮助!