Search code examples
flutterlistviewlisttile

Flutter cannot increment inside listtile, always returning 0


I want to increment number on trailing ListTile Flutter when ontap ListTile,
but always return to 0?
i'm using future builder fyi, thanks in advance

this my model

class ItemModel {
  String name;
  String price;
  String image;
  bool isSelected = false;
  int countSelected = 0;

  ItemModel(
    this.name,
    this.price,
    this.image,
  );
}

This method to get data from api json from local server

  Future<List<ItemModel>> _getItems() async {
    List<ItemModel> listItems = [];
    var url = Uri.parse(BASEURLLOCAL.apiGetItems);
    var data = await http.get(url);
    var jsonData = jsonDecode(data.body);

    for (var p in jsonData) {
      ItemModel item = ItemModel(
        p["name"],
        p["price"],
        p["image"],
        // p["PRODUCT_NAME"],
        // p["PRICE_SELL"],
        // p["FILENAME"],
      );
      listItems.add(item);
    }
    return listItems;
  }

and this the listview builder

  @override
  Widget build(BuildContext context) {
    
    return FutureBuilder<List<ItemModel>>(
      future: _getItems(),
      builder: (context, snapshot) {
        if (snapshot.data == null) {
          return Container(
            child: Center(
              child: CircularProgressIndicator(),
            ),
          );
        } else {
          return ListView.builder(
            shrinkWrap: true,
            itemCount: snapshot.data.length,
            itemBuilder: (BuildContext contex, int idx) {
              if (_itemCount.length < snapshot.data.length) {
                _itemCount.add(0);
              }
              return Card(
                child: ListTile(
                  leading: Image.network(
                      BASEURLLOCAL.imgItem + snapshot.data[idx].image),
                  title: Text(snapshot.data[idx].name),
                  subtitle: Text(snapshot.data[idx].price),
                  // trailing: _buildTrailing(),
                  trailing: Text(snapshot.data[idx].countSelected.toString()),
                  onTap: () {
                    setState(() {
                      snapshot.data[idx].countSelected++;
                    });
                  },
                ),
              );
            },
          );
        }
      },
    );
  }

this is what the problem is


Solution

  • Try something like this, create a list

    List<ItemModel> listItems = [];
    

    then, in initState() call the _getItems()

    _getItems() async {
        var url = Uri.parse(BASEURLLOCAL.apiGetItems);
        var data = await http.get(url);
        var jsonData = jsonDecode(data.body);
    
        for (var p in jsonData) {
          ItemModel item = ItemModel(
            p["name"],
            p["price"],
            p["image"],
            // p["PRODUCT_NAME"],
            // p["PRICE_SELL"],
            // p["FILENAME"],
          );
          listItems.add(item);
        }
      }
    

    And remove FutureBuilder

    @override
      Widget build(BuildContext context) {
        return ListView.builder(
          shrinkWrap: true,
          itemCount: listItems.length,
          itemBuilder: (BuildContext context, int idx) {
            if (_itemCount.length < listItems.length) {
              _itemCount.add(0);
            }
            return Card(
              child: ListTile(
                leading: Image.network(BASEURLLOCAL.imgItem + listItems[idx].image),
                title: Text(listItems[idx].name),
                subtitle: Text(listItems[idx].price),
                // trailing: _buildTrailing(),
                trailing: Text(listItems[idx].countSelected.toString()),
                onTap: () {
                  setState(() {
                    listItems[idx].countSelected++;
                  });
                },
              ),
            );
          },
        );
      }
    

    By this way it won't fetch everytime when it rebuilds.