Search code examples
flutterasynchronousdartindex-error

RangeError (index): Invalid value: Valid value range is empty using async function


I'm trying to iterate over a List<ClassName> so I can later retrieve data from it. The data are retrieved from a json file inside the Future<List<ClassName>> _getValues() async function. The problem is that when I start the app I receive the "RangeError (index): Invalid value: Valid value range is empty: -1", but after few moments the screen shows the correct informations. I'm new to Flutter but from what I understand the iteration is at first happening through a empty list. This is the function i mentioned:

  Future<List<CountryData>> _getValues() async {
var countriesData = List<CountryData>();
var data = await http
    .get("https://opendata.ecdc.europa.eu/covid19/casedistribution/json");

var jsonData = json.decode(data.body);

for (var i in jsonData["records"].toList()) {
  countriesData.add(CountryData.fromJson(i));
}

return countriesData;

}

This is where I set the state of the list:

List<CountryData> _countriesData = List<CountryData>();
void initState() {
_getValues().then((value) {
  setState(() {
    _countriesData.addAll(value);
  });
});
super.initState();

}

this is where I get the data from said List:

int findState(String code) {
var index = _countriesData.length;
for (int i = 0; i < index; i++) {
  if (_countriesData[i].alpha3Code == (code)) {
    return i;
  }
}
return -1;

}

This is where i want to show it:

Widget build(BuildContext context) {
return Scaffold(
...
...
body: ListView(children: <Widget>[
      Text(_countriesData[findState(code)]])))

The CountryData class is:

class CountryData{
String alpha3Code;
String day;
String month;
String year;
CountryData(this.alpha3Code, this.day, this.month,this.year);
CountryData.fromJson(Map<String, dynamic> json){
      this.day = json['day'];
      this.month = json['month'];
      this.year = json['year'];
      this.alpha3Code = json['alpha3Code'];
      }
 }

Let me now if you need more info. Thanks


Solution

  • Your problem is that the build method is running before you have the data you want to display. One way of handling this is to use an 'isLoading' flag that you set to true before the http call and set to false (and call setState) when it returns the data. In the build method you check the flag and show a progress indicator if the flag is true. When it becomes false you show your ListView.