You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter天气应用数据为null时触发AlertDialog报context!=null不成立错误

报错原因
  • 你直接将异步方法showDialog当做Widget嵌入到了build的组件树中,showDialog返回的是Future对象,并非Flutter组件,不能放在组件结构里
  • 调用showDialog时没有传入必填的context参数,直接触发了context != null的断言报错
  • 状态控制变量weatherCondition没有在数据处理逻辑中赋值,状态判断逻辑完全不生效
修复步骤
  1. 调整updateUI逻辑,在检测到天气数据为空时,在绘制帧结束后触发弹窗,同时正确更新weatherCondition状态
  2. 删除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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.25 00:54:04