Using compute to read large data from json file in flutter

Issue

I am trying to read a lot of data from a JSON file in flutter. The data retrieval results in jank so I decided to use compute but then it didn’t return any results.

This is my code with compute that does not return data:

Future<List<City>> getCityList (BuildContext context) async{

    final response = await DefaultAssetBundle.of(context).loadString('Assets/citylist.json');
    final decoded = await compute(json.decode, response);
    return decoded.map<City>((json) => fromJson(json)).toList();
  }

This is my code without compute that does returns data but results in jank :

Future<List<City>> getCityList (BuildContext context) async{

    final response = await DefaultAssetBundle.of(context).loadString('Assets/citylist.json');
    final decoded = json.decode(response);
    return decoded.map<City>((json) => fromJson(json)).toList();
  }

This is the code for my Futurebuilder:

FutureBuilder(
        future:  getCityList(context),
        builder: (context, snapshot) {
            if (snapshot.hasData){
              return ListView.builder(
                  itemCount: snapshot.data?.length ?? 0,
                  itemBuilder: (BuildContext context, int index) {
                    return FlatButton(
                      onPressed: (){

                      },
                      child: Container(
                        child: Text(snapshot.data[index].name, style: TextStyle(fontSize: 20.0, color: Theme.of(context).accentColor),),
                        padding: const EdgeInsets.all(15.0),
                      ),
                    );
                  }
              );
            }
            return Center(child: CircularProgressIndicator(),);
          })

Solution

You cannot pass object methods(or closures) – instead, you need to path top-level functions.

Should be await compute(jsonDecode, response)
Where jsonDecode is top-level function from json.dart.(just use jsonDecode func instead of json.decode)

Also, I suggest creating a method like decodeCities where you can decode and map your JSON.
Here u can find a sample and more details
Invalid argument(s): Illegal argument in isolate message : (object is a closure – Function 'createDataList':.)

Updated:

For tests I use next JSON(12mb)
https://raw.githubusercontent.com/lutangar/cities.json/master/cities.json

final decoded = await compute(decode, response);
print(decoded.length);

List<City> decode(dynamic obj) {
  final decoded = jsonDecode(obj);
  return decoded.map<City>((json) => City.fromJson(json)).toList();
}

class City {
  String country;
  String name;
  String lat;
  String lng;

  City({this.country, this.name, this.lat, this.lng});

  City.fromJson(Map<String, dynamic> json) {
    country = json['country'];
    name = json['name'];
    lat = json['lat'];
    lng = json['lng'];
  }

  Map<String, dynamic> toJson() {
    final Map<String, dynamic> data = new Map<String, dynamic>();
    data['country'] = this.country;
    data['name'] = this.name;
    data['lat'] = this.lat;
    data['lng'] = this.lng;
    return data;
  }
}

Answered By – Yauhen Sampir

Answer Checked By – Mary Flores (FlutterFixes Volunteer)

Leave a Reply

Your email address will not be published.