Home > other >  Can't retrieve more than one info from api in Flutter
Can't retrieve more than one info from api in Flutter

Time:08-17

I'm trying to fetch both temperature and icon name from Openweathermap api. The problem occurs when I try to to fetch icon(or rather icon name).

It returns an error :

Unhandled Exception: type 'String' is not a subtype of type 'int' of 'index' And I can't seem to find where the problem is. In other models I have other data types and it works fine, here it doesn't.

When I add icon to model, view returns null for temperature.

Here is code for weather model:

class WeatherData {
  int? temp;
  String? icon;

  WeatherData({
    this.temp,
    this.icon
  });

  WeatherData.fromJson(dynamic json) {
    var tempInKelvin = json["main"]["temp"];
    temp = (tempInKelvin - 273.15).round();
    icon = json["weather"]["icon"];
  }
}

This is weather service:

class WeatherService {
  final apiKey = "7e23369c183254302bda0471cc3f848c";

  Future<WeatherData?> getWeatherForLocation(LocationData location) async {
    WeatherData? weatherData;

    var params = {
      "lat": location.lat.toString(),
      "lon": location.lon.toString(),
      "city": location.city,
      "appId": apiKey,
    };
    var url = Uri.http('api.openweathermap.org', '/data/2.5/weather', params);
    Response response = await get(url);

    if (response.statusCode == HttpStatus.ok) {
      var jsonResponse = jsonDecode(response.body) as Map<String, dynamic>;
      weatherData = WeatherData.fromJson(jsonResponse);
      print("Request successful: $jsonResponse");
      return weatherData;
    } else {
      print("Request failed with status: ${response.statusCode}");
      return weatherData;
    }
  }
}

This is weather controller:

class WeatherController extends GetxController {
  final WeatherService _weatherService = Get.find();

  Rxn<LocationData> locationData = Rxn();
  Rxn<WeatherData> weatherData = Rxn();

  // RxString infoText = "...".obs;

  String get address =>
      "${locationData.value?.city},${locationData.value?.county}, ${locationData.value?.country}";

  String get temperature => "${weatherData.value?.temp}";
  // String get icon => "${weatherData.value?.icon}";

  @override
  void onInit() async {
    super.onInit();
    await getCurrentLocation();
    await getTemperatureForCurrentLocation();
    await getWeatherIcon();
  }

  getCurrentLocation() async {
    LocationData? location = await _weatherService.getCurrentLocation();
    print(location?.city);
    locationData.value = location;
  }

  getTemperatureForCurrentLocation() async {
    if (locationData.value != null) {
      weatherData.value=
          await _weatherService.getWeatherForLocation(locationData.value!);
      // _getInfoText(weatherData.value?.temp);
    }
  }
}

CodePudding user response:

Looking at their API docs, it seems that weather contains an array of objects (as a result, you need an integer index to figure out which one you want).

https://openweathermap.org/current

To fix it, you can simply opt to always use the first object in the weather array and take the icon/description from that:

"weather": [
    {
      "id": 800,
      "main": "Clear",
      "description": "clear sky",
      "icon": "01d"
    }
  ],

Which is:

icon = json["weather"][0]["icon"];

CodePudding user response:

Can you please check this:

var tempInKelvin = double.parse(json["main"]["temp"]);

or this if your number is integer:

var tempInKelvin = int.parse(json["main"]["temp"]);
  • Related