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

Flutter应用启动默认显示当前位置天气的实现方案问询

问题描述

我的Flutter应用当前启动流程是:先进入Getting_City_Name页面获取城市名称(再通过城市名称转换为经纬度),之后进入主页展示天气数据,用户可返回该页面切换城市。现在希望修改为应用启动时直接显示当前位置的天气数据,无需进入获取城市名称页面。

已通过geolocator插件实现获取当前经纬度的函数,只需将这些值作为默认参数传入从OpenWeatherAPI获取天气数据的Future函数,同时保留支持传入用户输入城市对应经纬度的功能。


当前实现代码

主页Scaffold核心代码

Container(
        padding: EdgeInsets.all(20),
        child: SingleChildScrollView(
          scrollDirection: Axis.vertical,
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              Row(
                children: [
                  Consumer<CityProvider>(
                    builder: ((context, value, child) => Text(
                          value.cityInfo!.name.toString(),
                          style: TextStyle(
                              color:
                                  myColor.secondaryColor.withOpacity(0.7),
                              fontWeight: FontWeight.bold,
                              fontSize: 35),
                        )),
                  ),
                  SizedBox(
                    width: 7,
                  ),
                  Padding(
                    padding: const EdgeInsets.only(top: 8.0),
                    child: Consumer<CityProvider>(
                      builder: ((context, value, child) => Text(
                            details.localizedName.toString(),
                            style: TextStyle(
                                fontWeight: FontWeight.bold,
                                fontSize: 20,
                                color: Color.fromARGB(255, 100, 86, 86)
                                    .withOpacity(.4)),
                          )),
                    ),
                  ),
                ],
              ),
              Consumer<CityProvider>(
                  builder: ((context, value, child) => Text(
                        '${DateFormat('EEE, MMM d, hh:mm aaa').format(value.weatherInfo!.time)}',
                        style: TextStyle(
                            fontSize: 20,
                            color: Color.fromARGB(163, 87, 89, 90)),
                      ))),

Provider类代码

class CityProvider extends ChangeNotifier {
  CityInfo? cityInfo;
  WeatherInfo? weatherInfo;
  PollutionInfo? pollutionInfo;
  List<FiveDayForcastData> fiveDayData = [];
  
  List<double> minTemp = [];
  List<String> iconString = [];
  List<DateTime> time = [];
  List<String> day = [];
  List<String> date = [];
  //date chnages(i.e 10/11 becomes 10/12) on jth terms)
  List<int> j = [0, 5, 13, 21, 29];
  List<int> degreeofWind = [];

  Future<void> cityName(String cityName, lat, lang) async {
    cityInfo = await gettingCityData(cityName);

    notifyListeners();
  }

  Future<void> gettingTheWeather(lat, lang) async {
    weatherInfo = await gettingWeatherData(lat, lang);

    notifyListeners();
  }
}

天气数据获取函数

Constants myConstaints = Constants();

Future<WeatherInfo> gettingWeatherData(lat, long) async {
  var url = Uri.parse(
      'https://api.openweathermap.org/data/2.5/weather?lat=$lat&lon=$long&units=metric&appid=${myConstaints.apiKey}');
  var response = await http.get(url);
  if (response.statusCode == 200) {
    return WeatherInfo.fromJson(jsonDecode(response.body));
  } else
    throw Exception('failed');
}

解决方案

1. 修改天气数据函数,添加默认参数逻辑

调整gettingWeatherData函数,支持不传经纬度时自动使用当前位置的经纬度(复用你已实现的getCurrentLocation函数):

Constants myConstaints = Constants();

// 你已实现的获取当前经纬度函数(示例结构)
Future<Position> getCurrentLocation() async {
  // 权限检查与位置获取逻辑
  bool serviceEnabled = await Geolocator.isLocationServiceEnabled();
  if (!serviceEnabled) return Future.error('定位服务未开启');

  LocationPermission permission = await Geolocator.checkPermission();
  if (permission == LocationPermission.denied) {
    permission = await Geolocator.requestPermission();
    if (permission == LocationPermission.denied) return Future.error('定位权限被拒绝');
  }
  if (permission == LocationPermission.deniedForever) return Future.error('定位权限永久拒绝');

  return await Geolocator.getCurrentPosition();
}

// 修改后的天气数据函数
Future<WeatherInfo> gettingWeatherData({double? lat, double? long}) async {
  // 未传入经纬度时,使用当前位置
  if (lat == null || long == null) {
    final currentPos = await getCurrentLocation();
    lat = currentPos.latitude;
    long = currentPos.longitude;
  }

  var url = Uri.parse(
      'https://api.openweathermap.org/data/2.5/weather?lat=$lat&lon=$long&units=metric&appid=${myConstaints.apiKey}');
  var response = await http.get(url);
  if (response.statusCode == 200) {
    return WeatherInfo.fromJson(jsonDecode(response.body));
  } else
    throw Exception('获取天气数据失败');
}

2. 调整Provider的天气获取方法

修改CityProvider中的gettingTheWeather方法,支持无参数调用,同时补充城市信息的获取逻辑:

class CityProvider extends ChangeNotifier {
  // ... 原有代码不变 ...

  // 修改为可选参数,支持无参数调用
  Future<void> gettingTheWeather({double? lat, double? lang}) async {
    try {
      weatherInfo = await gettingWeatherData(lat: lat, long: lang);
      // 从天气接口返回数据中提取城市名(OpenWeatherAPI返回的name字段)
      cityInfo = CityInfo(name: weatherInfo!.name);
      notifyListeners();
    } catch (e) {
      // 异常处理,可根据需求添加提示
      debugPrint('加载天气失败: $e');
    }
  }

  // 保留原有切换城市的方法,适配新逻辑
  Future<void> switchCity(String cityName) async {
    cityInfo = await gettingCityData(cityName);
    // 根据城市经纬度获取天气
    await gettingTheWeather(lat: cityInfo!.lat, lang: cityInfo!.lon);
    notifyListeners();
  }
}

3. 启动主页时自动加载当前位置天气

在主页的initState中调用Provider的无参数gettingTheWeather方法:

class HomePage extends StatefulWidget {
  const HomePage({super.key});

  @override
  State<HomePage> createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  @override
  void initState() {
    super.initState();
    // 启动时自动加载当前位置天气
    Provider.of<CityProvider>(context, listen: false).gettingTheWeather();
  }

  @override
  Widget build(BuildContext context) {
    // 原有主页Scaffold代码不变
    return Scaffold(
      // ... 你的主页UI ...
    );
  }
}

4. 补充权限配置与异常提示

  • 在AndroidManifest.xml中添加定位权限:
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
    
  • 在Info.plist中添加iOS定位权限描述:
    <key>NSLocationWhenInUseUsageDescription</key>
    <string>需要获取您的位置以显示当地天气</string>
    
  • 可在Provider的异常捕获中添加SnackBar提示用户:
    if (mounted) {
      ScaffoldMessenger.of(context).showSnackBar(
        SnackBar(content: Text('加载天气失败: $e')),
      );
    }
    

内容的提问来源于stack exchange,提问作者mohitnx

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 13:15:15