Search code examples
flutterdata-consistency

Flutter List after storing all data in a for-loop, when out of loop replace all stored records with the last record. Why's that?


I want to pass data from json to a list. I load the list with data into a for-loop, and it works as expected, loading 6 records into my list. But when I verify when for-loop is done, my list keep only the last data in all 6 records. Why's that? This is my code:

    class LoadData {
          loadSalesData() async {
              String optiune = 'gen';
            String numeServer = Global.server;
            String tabel = Global.tabel;
            SalesData sd = SalesData("", 0.00);
            List<SalesData> sData = [];
            Loader kk = Loader();
            kk
                .searchOnServer(tabel: tabel, numeServer: numeServer, optiune: optiune, dataInceput: "2022-06-30", dataSfarsit: "2022-07-23")
                .then((rezultat) async {
              try {
                rezultat = "[" + rezultat + "]";
               
                var _json = jsonDecode(rezultat);
                Global.dataChart = [];
        
                for (int i = 0; i < _json.length; i++) {
                  // window.alert(_json[i]['partener'] + " Lenght:" + _json.length.toString());
                  sd.partener = _json[i]['partener'];
                  sd.sales = double.parse(_json[i]['Sales']);
                 
                  Global.dataChart.add(sd);
                 //This show the list correctly with all data from server
                  window.alert("Into for-loop $i:" + Global.dataChart[i].partener);
                }
        //This shows only the last record no matter the List index (i.e. [0],[1]...etc
                window.alert("Outside for-loop: " + Global.dataChart[0].partener);
        //This shows the same value as the previous
                window.alert("Outside for-loop: " + Global.dataChart[1].partener);
              } catch (e) {
                print(e);
              }
            });
          }
        }
        
        //Global.dataChart is defined in a separate class as static List<SalesData> dataChart = [];
        //and class SalesData is..
        
        class SalesData {
          String partener;
          double sales;
        
          SalesData(this.partener, this.sales);
        
        }


Solution

  • It is because you're editing the same instance of SalesData sd and dart uses call by reference on Objects of non-primitive types.

    Put SalesData sd = SalesData("", 0.00); in the loop instead.

    Like so:

                for (int i = 0; i < _json.length; i++) {
                      SalesData sd = SalesData("", 0.00);
                      // window.alert(_json[i]['partener'] + " Lenght:" + _json.length.toString());
                      sd.partener = _json[i]['partener'];
                      sd.sales = double.parse(_json[i]['Sales']);
                     
                      Global.dataChart.add(sd);
                     //This show the list correctly with all data from server
                      window.alert("Into for-loop $i:" + Global.dataChart[i].partener);
                    }
    

    To easily reproduce and better understand, try this:

    void main() {
      final x = X("random");
      final l = [];
      for(int i =0; i < 3; i ++){
        x.a = i.toString();
        l.add(x);
      }
      l.forEach((e) => print(e.a));
    }
    
    class X{
      String a;
      X(this.a);
    }