Clima天气应用报错LateInitializationError:latitude字段未初始化求助
Clima天气应用初始化错误排查与修复
错误信息
[ERROR:flutter/lib/ui/ui_dart_state.cc(198)] Unhandled Exception: LateInitializationError: Field 'latitude' has not been initialized. E/flutter (24924): #0 Location.latitude (package:clima/services/location.dart) E/flutter (24924): #1 WeatherModel.getLocationWeather (package:clima/services/weather.dart:23:25) E/flutter (24924): #2 _LoadingScreenState.getLocationData (package:clima/screens/loading_screen.dart:22:23)
问题根源
- 未初始化的
late变量:Location类中用late修饰latitude和longitude,但当getCurrentLocation因权限缺失、定位失败等异常抛出时,这两个变量不会被赋值,后续访问直接触发初始化错误。 - 异常处理缺失闭环:
getCurrentLocation仅打印异常,未处理定位失败后的逻辑,导致后续代码仍尝试访问未初始化的变量。 - 定位权限未配置:
Geolocator库需要定位权限,若未在项目配置中声明或动态请求,会直接导致定位失败。
解决方案
1. 重构Location类,替换late为可空类型
将latitude和longitude改为可空类型,同时增加权限检查与定位结果返回:
import 'package:geolocator/geolocator.dart'; class Location{ double? longitude; double? latitude; Future<bool> getCurrentLocation() async { try { // 检查并请求定位权限 LocationPermission permission = await Geolocator.checkPermission(); if (permission == LocationPermission.denied) { permission = await Geolocator.requestPermission(); if (permission == LocationPermission.denied) { return false; } } Position position = await Geolocator.getCurrentPosition(desiredAccuracy: LocationAccuracy.low); latitude = position.latitude; longitude = position.longitude; return true; } catch (exception) { print(exception); return false; } } }
2. 修改WeatherModel,增加定位有效性检查
在创建网络请求前,确认定位是否成功:
import 'package:clima/services/location.dart'; import 'package:clima/services/networking.dart'; const String apiKey = '304dd36c502250baab7c7f8216ec4ff2'; const String openWeatherMapURL = 'https://api.openweathermap.org/data/2.5/weather'; class WeatherModel { Future<dynamic> getCityWeather(String cityName) async { NetworkHelper networkHelper = NetworkHelper('$openWeatherMapURL?q=$cityName&appid=$apiKey&units=metric'); var weatherData = await networkHelper.getData(); return weatherData; } Future<dynamic> getLocationWeather() async { Location location = Location(); bool isLocationSuccess = await location.getCurrentLocation(); // 校验定位结果有效性 if (!isLocationSuccess || location.latitude == null || location.longitude == null) { return null; } NetworkHelper networkHelper = NetworkHelper('$openWeatherMapURL?lat=${location.latitude}&lon=${location.longitude}&appid=$apiKey&units=metric'); var weatherData = await networkHelper.getData(); return weatherData; } // 以下方法保持不变 String getWeatherIcon(int condition) { if (condition < 300) { return '🌩'; } else if (condition < 400) { return '🌧'; } else if (condition < 600) { return '☔️'; } else if (condition < 700) { return '☃️'; } else if (condition < 800) { return '🌫'; } else if (condition == 800) { return '☀️'; } else if (condition <= 804) { return '☁️'; } else { return '🤷'; } } String getMessage(int temp) { if (temp > 25) { return 'It\'s 🍦 time'; } else if (temp > 20) { return 'Time for shorts and 👕'; } else if (temp < 10) { return 'You\'ll need 🧣 and 🧤'; } else { return 'Bring a 🧥 just in case'; } } }
3. 配置定位权限
- Android:在
android/app/src/main/AndroidManifest.xml中添加权限:
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
- iOS:在
ios/Runner/Info.plist中添加:
<key>NSLocationWhenInUseUsageDescription</key> <string>需要获取您的位置来显示当地天气</string> <key>NSLocationAlwaysUsageDescription</key> <string>需要获取您的位置来显示当地天气</string>
4. 优化LoadingScreen的异常处理
定位失败时显示提示,避免无效跳转:
import 'package:flutter/material.dart'; import 'package:clima/screens/location_screen.dart'; import 'package:clima/services/weather.dart'; import 'package:flutter_spinkit/flutter_spinkit.dart'; class LoadingScreen extends StatefulWidget { @override State<StatefulWidget> createState() { return _LoadingScreenState(); } } class _LoadingScreenState extends State<LoadingScreen> { @override void initState() { super.initState(); getLocationData(); } void getLocationData() async { WeatherModel weatherModel = WeatherModel(); var weatherData = await weatherModel.getLocationWeather(); if (weatherData == null) { ScaffoldMessenger.of(context).showSnackBar( const SnackBar(content: Text('定位失败,请检查权限或重试')), ); return; } Navigator.push( context, MaterialPageRoute( builder: (context) => LocationScreen( locationWeather: weatherData, ), ), ); } @override Widget build(BuildContext context) { return Scaffold( body: Center( child: SpinKitSpinningLines( color: Colors.white, size: 50.0, ), ), ); } }
额外优化点
- LocationScreen中替换固定文本为动态变量:
// 替换温度与图标组件 Text( '$temperature°', style: kTempTextStyle, ), Text( weatherIcon, style: kConditionTextStyle, ), // 替换底部提示文本 Text( "$weatherMessage in $cityName!", textAlign: TextAlign.right, style: kMessageTextStyle, ),
- CityScreen中修正
Null为Dart关键字小写null:
if(typedName != null) { var weatherData = await weather.getCityWeather(typedName); updateUI(weatherData); }
内容的提问来源于stack exchange,提问作者Kshitiz Shrivastava
相关产品推荐
相关产品推荐

