Home > Enterprise >  Flutter RangeError (index): Invalid value: Only valid value is 0: 2 or RangeError (index): Invalid v
Flutter RangeError (index): Invalid value: Only valid value is 0: 2 or RangeError (index): Invalid v

Time:02-04

First of all, I am an amateur and I thank you in advance for your help !

In my project, I retrieve data from Cloud Firestore via this function :

recupereOrganisations(pays) async {

    listeOrganisations.clear();

    try{
      final reponseGet = (await FirebaseFirestore.instance.collection("Organisations").where("Pays", isEqualTo: "Belgium").get())
          .docs.map((e) => e.data());

      reponseGet.forEach((element) {
        listeOrganisations.add(Organisations(
            nom: "${element["Nom"]}",
            activite: "${element["Activité"]}",
            motcle1: "${element["MotCle1"]}",
            motcle2: "${element["MotCle2"]}",
            motcle3: "${element["MotCle3"]}",
            nbpmt: element["NbPmt"],
            photo: "${element["Photo"]}",
            latitude: "${element["Latitude"]}",
            longitude: "${element["Longitude"]}",
            pays: "${element["Pays"]}",
        ));
      });
      listeOrganisations.sort((a,b) => a.nbpmt!.compareTo(b.nbpmt!));

      listeOrganisations.forEach((element) {
        print("Le nom est : ${element.nom} et le nombre de paiements est de ${element.nbpmt}");
      });// this is a test to ensure everything is working (test successful)

      return listeOrganisations;
    }
    catch(e){
      print(e);
    }
  }

So, my list is populated with the data stored in Firebase and afterward the list is sorted. This works until here.

Problem arise when I try to 'use' the list in my build scaffold. Here is the code :

@override
  Widget build(BuildContext context) {
    //recupereOrganisations("Belgium");
    //print(" l'élément à imprimer est ${recupereOrganisations[2].activite}");
    return Scaffold(
      backgroundColor: noirFond,
      appBar: appbar,
      body: widgetListeTrieePmt(context),
    );
  }

  Widget widgetListeTrieePmt (context){
    recupereOrganisations("Belgium");
    print(" test sur la liste ${listeOrganisations[2].activite}");
      return Container(

After the return statement it is no more relevant for the error...

The error comes at the line where I do the print, I understand from the error message that the list 'listeOrganisations' is empty when I try to print it.

Because the function works, I guess that it comes from the async thing, the code continuing before the completion of the asynchronous function...

I tried several things but none of them brought a solution :

  • put a condition in the return of the build : if ((listeOrganisation == null) ||(listeOrganisation.isEmpty)) and call the widget only when false
  • same as before but for the body of the Scaffold
  • call the function in the init (and also adding a .then((value) => setState the list
  • putting a setSate at the end of the function (there it seems it makes the function looping because the print of the list (the foreach loop) doesn't stop repeating itself.
  • ...

So, I am stuck.

Thanks in advance for your help !

Bernard

CodePudding user response:

your error comes from the print statement

 print(" test sur la liste ${listeOrganisations[2].activite}");

You are trying to access an index that doesn't exist in the array. Always remember dart has a zero-based array index, the first item in the list has an index of 0.

you can check if the array is empty before trying to access any item in it.

for instance

if(liseOrganisations.isNotEmpty){
  print(" test sur la liste ${listeOrganisations[0].activite}");
}

in this case I am accessing the first item of the array.

in a situation where you want to access the 3rd item in the array, you need to check that the array has up to 3 items

if(liseOrganisations.length >= 3){
  print(" test sur la liste ${listeOrganisations[2].activite}");
}

CodePudding user response:

I found a solution, problem was coming from the asynchronous task. I took a boolean (donneesRecues) that is initialized on false an call the recupereOrganisation function in the init with a .then that puts the boolean to true. Here is the code :

 void initState() {
    // TODO: implement initState
    recupereOrganisations("Belgium").then((value) {
      setState(() {
        donneesRecues = true;
      });
    });
    super.initState();
  }

After, in the build I return a Scaffold with a Container as child and for the child of this Container I put a condition on the boolean :

 return Scaffold(
      backgroundColor: noirFond,
      appBar: appbar,
      body: Container(
        alignment: Alignment.center,
        width: MediaQuery.of(context).size.width,
        height: MediaQuery.of(context).size.height,
        child : (donneesRecues==false)? onPatiente(context): onAffiche(context),
      ),
    );

with onPatiente(context) that shows a waiting page and onAffiche(context) that do what I wanted to do.

Thanks to those who took the time to answer me !

Bernard

  • Related