Flutter天气应用数据为null时触发AlertDialog报context!=null不成立错误
报错原因
- 你直接将异步方法
showDialog当做Widget嵌入到了build的组件树中,showDialog返回的是Future对象,并非Flutter组件,不能放在组件结构里 - 调用
showDialog时没有传入必填的context参数,直接触发了context != null的断言报错 - 状态控制变量
weatherCondition没有在数据处理逻辑中赋值,状态判断逻辑完全不生效
修复步骤
- 调整
updateUI逻辑,在检测到天气数据为空时,在绘制帧结束后触发弹窗,同时正确更新weatherCondition状态 - 删除build方法中嵌入的
showDialog逻辑,替换为异常状态下的占位组件即可
修复后完整代码
import 'package:clima/services/weather.dart'; import 'package:clima/utilities/constants.dart'; import 'package:flutter/material.dart'; import 'city_screen.dart'; class LocationScreen extends StatefulWidget { LocationScreen({this.locationWeather}); final locationWeather; @override _LocationScreenState createState() => _LocationScreenState(); } class _LocationScreenState extends State<LocationScreen> { WeatherModel weather = WeatherModel(); String? weatherMessage; String? cityName; int temperature = 0; String weatherIcon = ''; bool weatherCondition = false; @override void initState() { super.initState(); updateUI(widget.locationWeather); } void updateUI(dynamic weatherData) { if (weatherData == null) { setState(() { temperature = 0; weatherIcon = 'Error!'; weatherCondition = false; }); // 等待当前帧绘制完成后再弹出弹窗,避免build过程中修改UI的冲突 WidgetsBinding.instance.addPostFrameCallback((_) { showDialog( // 必须传入当前context context: context, builder: (BuildContext context) => AlertDialog( content: const Text('Unable to get weather data!'), actions: [ RaisedButton( onPressed: () => Navigator.pop(context), child: const Text('OK'), ), ], ), ); }); return; } setState(() { double temp = weatherData['main']['temp']; temperature = temp.toInt(); var conditionNumber = weatherData['weather'][0]['id']; weatherIcon = weather.getWeatherIcon(conditionNumber); weatherMessage = weather.getMessage(temperature); cityName = weatherData['name']; weatherCondition = true; }); } @override Widget build(BuildContext context) { return Scaffold( body: Container( decoration: BoxDecoration( image: DecorationImage( image: const AssetImage('images/location_background.jpg'), fit: BoxFit.cover, colorFilter: ColorFilter.mode( Colors.white.withOpacity(0.8), BlendMode.dstATop), ), ), constraints: const BoxConstraints.expand(), child: SafeArea( child: Column( mainAxisAlignment: MainAxisAlignment.spaceBetween, crossAxisAlignment: CrossAxisAlignment.stretch, children: <Widget>[ Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: <Widget>[ FlatButton( onPressed: () async { var weatherData = await weather.getLocationWeather(); updateUI(weatherData); }, child: const Icon( Icons.near_me, size: 50.0, ), ), FlatButton( onPressed: () { Navigator.push( context, MaterialPageRoute(builder: (context) => const CityScreen()), ); }, child: const Icon( Icons.location_city, size: 50.0, ), ), ], ), Padding( padding: const EdgeInsets.only(left: 15.0), child: Row( children: <Widget>[ Text( '$temperature°', style: kTempTextStyle, ), Text( weatherIcon, style: kConditionTextStyle, ), ], ), ), // 移除错误的showDialog调用,异常状态下展示提示文本即可 weatherCondition ? Padding( padding: const EdgeInsets.fromLTRB(0.0, 0.0, 15.0, 40.0), child: Text( '$weatherMessage $cityName!', textAlign: TextAlign.right, style: kMessageTextStyle, ), ) : const Padding( padding: EdgeInsets.fromLTRB(0.0, 0.0, 15.0, 40.0), child: Text( '无法获取天气数据,请检查网络和定位权限', textAlign: TextAlign.right, style: kMessageTextStyle, ), ) ], ), ), ), ); } }
额外说明
如果使用的是Flutter 3.0+版本,代码中用到的FlatButton、RaisedButton已经被标记为废弃,可以替换为TextButton和ElevatedButton使用。
内容的提问来源于stack exchange,提问作者Ahmed Loutfy
相关产品推荐
相关产品推荐

