Flutter天气应用首次运行值为null、热重载后才显示如何解决?
问题根本原因
你遇到的现象核心原因是两点:
- Flutter首次渲染页面时,
getLocation和getData都是异步方法,不会阻塞UI线程执行,build方法会在定位请求、天气接口请求完成前就执行完毕,此时你声明的CityName/Temperature/Description几个变量还没被赋值,默认是null,所以首次渲染显示null。 - 你在异步方法中完成变量赋值后,没有调用
setState通知Flutter框架状态发生变更、需要重新渲染页面,所以页面不会主动更新数值。而你执行热重载时,相当于强制触发了一次页面重绘,此时变量已经赋值完成,所以数值就正常显示了。
修复方案
只需要在getData方法中完成所有变量赋值后,调用setState即可,修改后的getData代码如下:
void getData() async{ var url = Uri.parse('https://api.openweathermap.org/data/2.5/weather?lat=$Latitude&lon=$Longitude&appid=$appid&units=metric'); http.Response response = await http.get(url); if (response.statusCode == 200){ String Data = response.body; var city = jsonDecode(Data)['name']; var temp = jsonDecode(Data)['main']['temp']; var condition = jsonDecode(Data)['weather'][0]['description']; // 赋值完成后调用setState触发UI刷新 setState(() { CityName = city; Temperature = temp; Description = condition; }); }else{ print(response.statusCode); } }
另外建议你可以额外加个加载状态,首次渲染时显示加载指示器,避免用户看到null值,体验更好:
- 先声明一个加载状态变量:
bool isLoading = true; - 在
setState中同步更新加载状态:isLoading = false; build方法中根据加载状态显示不同内容:
@override Widget build(BuildContext context) { return MaterialApp( home: Scaffold( body: isLoading ? Center(child: CircularProgressIndicator()) : Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Center(child: Text('$CityName')), Center(child: Text('$Temperature')), Center(child: Text('$Description')), ], ) ), ); }
额外优化建议
Dart官方规范中,普通变量命名使用小驼峰格式,你当前的Longitude/Latitude/CityName等变量都是大驼峰格式,不符合规范,建议调整为longitude/latitude/cityName的写法,避免后续和类名混淆。
内容的提问来源于stack exchange,提问作者Vignesh Jagannadhan
相关产品推荐
相关产品推荐

