方法“[]”在 null 上调用。颤动天气应用程序

问题描述 投票:0回答:1

我有一些错误:

I/flutter (30216): NoSuchMethodError: 在 null 上调用了方法“[]”。 I/flutter (30216):接收器:空 我/颤振(30216):尝试调用:

这是我的 main.dart 代码:

import 'dart:convert';

import 'package:flutter/material.dart';
import 'package:flutter_weather/models/additionalWeatherData.dart';
import 'package:flutter_weather/models/geocode.dart';
import 'package:geolocator/geolocator.dart';
import 'package:http/http.dart' as http;
import 'package:latlong2/latlong.dart';

import '../models/dailyWeather.dart';
import '../models/hourlyWeather.dart';
import '../models/weather.dart';

class WeatherProvider with ChangeNotifier {
  String apiKey = '744b94562476e3686d8944d72c0bb1f2';
  late Weather weather;
  late AdditionalWeatherData additionalWeatherData;
  LatLng? currentLocation;
  List<HourlyWeather> hourlyWeather = [];
  List<DailyWeather> dailyWeather = [];
  bool isLoading = false;
  bool isRequestError = false;
  bool isSearchError = false;
  bool isLocationserviceEnabled = false;
  LocationPermission? locationPermission;
  bool isCelsius = true;

  String get measurementUnit => isCelsius ? '°C' : '°F';

  Future<Position?> requestLocation(BuildContext context) async {
    isLocationserviceEnabled = await Geolocator.isLocationServiceEnabled();
    notifyListeners();

    if (!isLocationserviceEnabled) {
      ScaffoldMessenger.of(context).showSnackBar(
        SnackBar(content: Text('Location service disabled')),
      );
      return Future.error('Location services are disabled.');
    }

    locationPermission = await Geolocator.checkPermission();
    if (locationPermission == LocationPermission.denied) {
      isLoading = false;
      notifyListeners();
      locationPermission = await Geolocator.requestPermission();
      if (locationPermission == LocationPermission.denied) {
        ScaffoldMessenger.of(context).showSnackBar(SnackBar(
          content: Text('Permission denied'),
        ));
        return Future.error('Location permissions are denied');
      }
    }

    if (locationPermission == LocationPermission.deniedForever) {
      isLoading = false;
      notifyListeners();
      ScaffoldMessenger.of(context).showSnackBar(SnackBar(
        content: Text(
          'Location permissions are permanently denied, Please enable manually from app settings',
        ),
      ));
      return Future.error('Location permissions are permanently denied');
    }

    return await Geolocator.getCurrentPosition();
  }

  Future<void> getWeatherData(
    BuildContext context, {
    bool notify = false,
  }) async {
    isLoading = true;
    isRequestError = false;
    isSearchError = false;
    if (notify) notifyListeners();

    Position? locData = await requestLocation(context);

    if (locData == null) {
      isLoading = false;
      notifyListeners();
      return;
    }

    try {
      currentLocation = LatLng(locData.latitude, locData.longitude);
      await getCurrentWeather(currentLocation!);
      await getDailyWeather(currentLocation!);
    } catch (e) {
      print(e);
      isRequestError = true;
    } finally {
      isLoading = false;
      notifyListeners();
    }
  }

  Future<void> getCurrentWeather(LatLng location) async {
    Uri url = Uri.parse(
      'https://api.openweathermap.org/data/2.5/weather?lat=${location.latitude}&lon=${location.longitude}&units=metric&appid=$apiKey',
    );
    try {
      final response = await http.get(url);
      final extractedData = json.decode(response.body) as Map<String, dynamic>;
      weather = Weather.fromJson(extractedData);
      print('Fetched Weather for: ${weather.city}/${weather.countryCode}');
    } catch (error) {
      print(error);
      isLoading = false;
      this.isRequestError = true;
    }
  }

  Future<void> getDailyWeather(LatLng location) async {
    isLoading = true;
    notifyListeners();

    Uri dailyUrl = Uri.parse(
      'https://api.openweathermap.org/data/2.5/onecall?lat=${location.latitude}&lon=${location.longitude}&units=metric&exclude=minutely,current&appid=$apiKey',
    );
    try {
      final response = await http.get(dailyUrl);
      final dailyData = json.decode(response.body) as Map<String, dynamic>;
      additionalWeatherData = AdditionalWeatherData.fromJson(dailyData);
      List dailyList = dailyData['daily'];
      List hourlyList = dailyData['hourly'];
      hourlyWeather = hourlyList
          .map((item) => HourlyWeather.fromJson(item))
          .toList()
          .take(24)
          .toList();
      dailyWeather =
          dailyList.map((item) => DailyWeather.fromDailyJson(item)).toList();
    } catch (error) {
      print(error);
      isLoading = false;
      this.isRequestError = true;
    }
  }

  Future<GeocodeData?> locationToLatLng(String location) async {
    try {
      Uri url = Uri.parse(
        'http://api.openweathermap.org/geo/1.0/direct?q=$location&limit=5&appid=$apiKey',
      );
      final http.Response response = await http.get(url);
      if (response.statusCode != 200) return null;
      return GeocodeData.fromJson(
        jsonDecode(response.body)[0] as Map<String, dynamic>,
      );
    } catch (e) {
      print(e);
      return null;
    }
  }

  Future<void> searchWeather(String location) async {
    isLoading = true;
    notifyListeners();
    isRequestError = false;
    print('search');
    try {
      GeocodeData? geocodeData;
      geocodeData = await locationToLatLng(location);
      if (geocodeData == null) throw Exception('Unable to Find Location');
      await getCurrentWeather(geocodeData.latLng);
      await getDailyWeather(geocodeData.latLng);
      // replace location name with data from geocode
      // because data from certain lat long might return local area name
      weather.city = geocodeData.name;
    } catch (e) {
      print(e);
      isSearchError = true;
    } finally {
      isLoading = false;
      notifyListeners();
    }
  }

  void switchTempUnit() {
    isCelsius = !isCelsius;
    notifyListeners();
  }
}

我尝试在网络中找到解决方案,但我看不到类似的东西。我从 GitHub 上获取了这个应用程序的开源项目,但没有任何关于它的文章。

flutter dart mobile openweathermap weather
1个回答
0
投票

了解错误发生在哪一行会有所帮助,但如果没有这些详细信息,我们仍然可以找到问题的潜在根源。

提供的代码示例中似乎有两个值是对

[]
运算符的调用的接收者,
dailyData
jsonDecode(response.body)[0] as Map<String, dynamic>

dailyData
初始化为:
final dailyData = json.decode(response.body) as Map<String, dynamic>;

这两种情况下的问题是,您将

json.decode(response.body)
的结果(即
dynamic
值)转换为
Map
,而没有检查所转换的值实际上是
Map
。在这种情况下,看起来至少在您的一种情况下
json.decode(response.body)
的结果实际上是
null
,因此不能成为
[]
呼叫的接收者。

这对你来说可能是个好主意

  • 在将其转换为
    json.decode(response.body)
    之前先检查
    Map
    的值,以确保它看起来像您所期望的那样
  • 强制转换为可为空的 Map(
    Map<String, dynamic>?
    ,请注意类型后面的
    ?
    ),并让编译器告诉您在哪里执行 null 不安全的操作
  • 或提供一个默认值,也许类似于
    jsonDecode(response.body)[0] as Map<String, dynamic> ?? <String, dynamic>{}
    (尽管最后一点我还没有测试过,也不是100%确定)
© www.soinside.com 2019 - 2024. All rights reserved.