Flutter 点击按钮首次不加载天气数据 第二次点击才正常加载问题求助
问题原因
你当前代码的执行逻辑是点击按钮后同时触发异步定位+天气请求、同步弹出对话框两个任务,异步请求还未执行完成、_data仍为空数组时,对话框已完成渲染,因此首次点击无数据展示。第二次点击时前一次请求已经把数据存入_data,因此可以正常展示内容。
解决方法
调整执行顺序,等异步的定位和天气请求全部执行完成后,再弹出对话框,修改步骤如下:
- 将
queryWeather方法返回值修改为Future<void> - 将
getCurrentLocation方法返回值修改为Future<void>,调用queryWeather时增加await关键字 - 按钮
onPressed改为异步函数,先awaitgetCurrentLocation执行完成,再调用showDialog弹出对话框
修改后完整代码
import 'package:flutter/material.dart'; import 'package:geolocator/geolocator.dart'; import 'package:weather/weather.dart'; void main() => runApp(MyAppp()); class MyAppp extends StatefulWidget { const MyAppp({ Key? key }) : super(key: key); @override _MyApppState createState() => _MyApppState(); } class _MyApppState extends State<MyAppp> { @override Widget build(BuildContext context) { return MaterialApp( home:ButtonPage() ); } } class ButtonPage extends StatefulWidget { const ButtonPage({ Key? key }) : super(key: key); @override _ButtonPageState createState() => _ButtonPageState(); } class _ButtonPageState extends State<ButtonPage> { String key = '856822fd8e22db5e1ba48c0e7d69844a'; late WeatherFactory ws; List<Weather> _data = []; double? lat, lon; // 加载状态避免重复点击 bool _isLoading = false; @override void initState() { super.initState(); ws = WeatherFactory(key); } Future<void> getCurrentLocation() async { var position = await Geolocator.getCurrentPosition( desiredAccuracy: LocationAccuracy.high); var lat = position.latitude; var long = position.longitude; print(lat); print(long); await queryWeather(lat,long); } Future<void> queryWeather(var lat,var long) async { print("Data: "+_data.toString()); FocusScope.of(context).requestFocus(FocusNode()); Weather weather = await ws.currentWeatherByLocation(lat, long); setState(() { _data = [weather]; }); } @override Widget build(BuildContext context) { return Scaffold( body: Center(child: RaisedButton( onPressed: _isLoading ? null : () async { setState(() { _isLoading = true; }); try { await getCurrentLocation(); if(!mounted) return; showDialog<void>( context: context, builder: (BuildContext context) { return Dialog( child: Center( child: ListView.builder( shrinkWrap: true, itemCount: _data.length, itemBuilder: (context, index) { return ListTile( title: Text("${_data[index].areaName}"), ); }, ), ), ); }, ); } catch(e) { // 可自行添加定位失败、网络请求失败的提示逻辑 print(e); } finally { if(mounted) { setState(() { _isLoading = false; }); } } }, child: _isLoading ? CircularProgressIndicator(color: Colors.white,) : Text("Button"), ),), ); } }
补充说明
如果想要更流畅的用户体验,也可以选择先弹出带加载动画的对话框,等天气数据请求完成后再更新对话框内容,避免用户在网络较慢时等待无反馈。
内容的提问来源于stack exchange,提问作者Deepak
相关产品推荐
相关产品推荐

