Search code examples
jsonflutterdio

NoSuchMethodError: The method 'forEach' was called on null


I get the error after fetching the data with Dio.

Exception has occurred.
NoSuchMethodError (NoSuchMethodError: The method 'forEach' was called on null.
Receiver: null
Tried calling: forEach(Closure: (String, dynamic) => Null))

I get the above error on this line jsonResponse.forEach((key, value) {

this is how I fetch the data from json:

    Future<List<AirQualityModel>> _getAirQuality() async {
var dio = Dio();
var cookieJar;
Response dioResponse;
Directory appDocDir = await getApplicationDocumentsDirectory();
String appDocPath = appDocDir.path;
try {
  cookieJar = PersistCookieJar(dir: appDocPath + "/.cookies/");
  dio.interceptors.add(CookieManager(cookieJar));
  dioResponse = await dio.get(
      "https://www.airvisual.com/api/v2/node/5ded3e13994dfe107f7013a0");
  debugPrint('dioResponse: ' + dioResponse.data.toString());
  debugPrint("response: " + dioResponse.statusMessage.toString());
  jsonResponse = json.decode(dioResponse.data);
  airqualityList = List<AirQualityModel>();
  jsonResponse?.forEach((key, value) {
    airqualityList = (jsonResponse['current'] as List)
        .map<AirQualityModel>((j) => AirQualityModel.fromJson(j))
        .toList();
  });
  debugPrint('List: $airqualityList');
  return airqualityList;
} catch (e) {
  print('catch error: $e');
}

}

and this is my airquality_model.dart

class AirQualityModel {
final int pm25;
final int co2;
final int humidity;
final int temperature;

AirQualityModel(this.pm25, this.co2, this.humidity, this.temperature);

AirQualityModel.fromJson(Map<String, dynamic> json)
  : pm25 = json['p2'],
    co2 = json['co'],
    humidity = json['hm'],
    temperature=json['tp'];
}

This is my debug console:

enter image description here

I've updated my code and I put a set state where I decode the json and now my debug console looks like this:

The following RangeError was thrown building:
RangeError (index): Invalid value: Valid value range is empty: 0

How can I resolve this error?


Solution

  • You can copy paste run full code below
    Step 1: dioResponse.data is Map , you do not need to do json.decode again
    Step 2: dioResponse.data["current"] is not a List, you can directly use Future<AirQualityModel>

    code snippet

    Future<AirQualityModel> _getAirQuality() async {
        var dio = Dio();
        var cookieJar;
        Response dioResponse;
        Directory appDocDir = await getApplicationDocumentsDirectory();
        String appDocPath = appDocDir.path;
        try {
          cookieJar = PersistCookieJar(dir: appDocPath + "/.cookies/");
          dio.interceptors.add(CookieManager(cookieJar));
          dioResponse = await dio.get(
              "https://www.airvisual.com/api/v2/node/5ded3e13994dfe107f7013a0");
    
          return AirQualityModel.fromJson(dioResponse.data["current"]);
        } catch (e) {
          print('catch error: $e');
        }
      }
    

    working demo

    enter image description here

    full code

    import 'dart:convert';
    import 'dart:io';
    
    import 'package:cookie_jar/cookie_jar.dart';
    import 'package:dio/dio.dart';
    import 'package:dio_cookie_manager/dio_cookie_manager.dart';
    import 'package:flutter/material.dart';
    import 'package:path_provider/path_provider.dart';
    
    class AirQualityModel {
      final double pm25;
      final double co2;
      final double humidity;
      final double temperature;
    
      AirQualityModel(this.pm25, this.co2, this.humidity, this.temperature);
    
      AirQualityModel.fromJson(Map<String, dynamic> json)
          : pm25 = json['p2'].toDouble(),
            co2 = json['co'].toDouble(),
            humidity = json['hm'].toDouble(),
            temperature = json['tp'].toDouble();
    }
    
    void main() {
      runApp(MyApp());
    }
    
    class MyApp extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          title: 'Flutter Demo',
          theme: ThemeData(
            primarySwatch: Colors.blue,
            visualDensity: VisualDensity.adaptivePlatformDensity,
          ),
          home: MyHomePage(title: 'Flutter Demo Home Page'),
        );
      }
    }
    
    class MyHomePage extends StatefulWidget {
      MyHomePage({Key key, this.title}) : super(key: key);
    
      final String title;
    
      @override
      _MyHomePageState createState() => _MyHomePageState();
    }
    
    class _MyHomePageState extends State<MyHomePage> {
      Future<AirQualityModel> _future;
    
      Future<AirQualityModel> _getAirQuality() async {
        var dio = Dio();
        var cookieJar;
        Response dioResponse;
        Directory appDocDir = await getApplicationDocumentsDirectory();
        String appDocPath = appDocDir.path;
        try {
          cookieJar = PersistCookieJar(dir: appDocPath + "/.cookies/");
          dio.interceptors.add(CookieManager(cookieJar));
          dioResponse = await dio.get(
              "https://www.airvisual.com/api/v2/node/5ded3e13994dfe107f7013a0");
    
          return AirQualityModel.fromJson(dioResponse.data["current"]);
        } catch (e) {
          print('catch error: $e');
        }
      }
    
      @override
      void initState() {
        _future = _getAirQuality();
        super.initState();
      }
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(
            title: Text(widget.title),
          ),
          body: FutureBuilder(
              future: _future,
              builder: (context, AsyncSnapshot<AirQualityModel> snapshot) {
                switch (snapshot.connectionState) {
                  case ConnectionState.none:
                    return Text('none');
                  case ConnectionState.waiting:
                    return Center(child: CircularProgressIndicator());
                  case ConnectionState.active:
                    return Text('');
                  case ConnectionState.done:
                    if (snapshot.hasError) {
                      return Text(
                        '${snapshot.error}',
                        style: TextStyle(color: Colors.red),
                      );
                    } else {
                      return Card(
                          elevation: 6.0,
                          child: Padding(
                            padding: const EdgeInsets.only(
                                top: 6.0, bottom: 6.0, left: 8.0, right: 8.0),
                            child: Row(
                              crossAxisAlignment: CrossAxisAlignment.start,
                              children: <Widget>[
                                Text("co2  ${snapshot.data.co2.toString()}"),
                                Spacer(),
                                Text(
                                  "pm25 ${snapshot.data.pm25.toString()}",
                                ),
                              ],
                            ),
                          ));
                      ;
                    }
                }
              }),
        );
      }
    }