3

My problem is how to sum all checked items values, and how to manage their changed at check/uncheck events? This is my method for check box toggle (check/uncheck) event.

holder.itemCheckBox.setOnClickListener(new View.OnClickListener() 
{
  @Override
  public void onClick(View v) 
  {
    if (((CheckBox) v).isChecked()) 
    {
      double price = Double.parseDouble(catalogDatabases.get(position).getPriceItem());
      holder.totalPrice = holder.totalPrice + price;
      holder.listener.respond(holder.totalPrice);
    } 
    else {
    }
  }
});
Rami Loiferman
  • 624
  • 4
  • 15
afiq
  • 91
  • 8

2 Answers2

1

So first of all don't rely on the view as data. I'll explain in your code

if (((CheckBox) v).isChecked())

You relying on view's isChecked method. This may cause a bug because of android list recycling mechanism.

You can read about it in the link below
How ListView's recycling mechanism works

TL;DR views are being recycled so when you scroll your list. So for example the user checked item number 3 and then scrolled the list down item number 13 for example may also be shown as checked even tho it isn't .

So when onClick triggers we need to save the checked state in some list

After the theoretical intro i'll show it in code.

//Here you'll need to create some boolean array or list to store
//checked not checked positions lets call it checked
boolean[] checkedArr = new boolean[catalogDatabases.size()];
// catalogDatabases.size represents your data set size
// note that all items will be false initially

    @Override
    public void onBindViewHolder(@NonNull final MyViewHolder holder, final int position) {
        /**
         * Other views binding.......
         */
        holder.itemCheckBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(CompoundButton buttonView,boolean isChecked) {
                checkedArr[position] = isChecked;
                sumAllCheckedAndNotify();
            }
        }
        );
    }

(I decided to do the calculation on every check it more straight forward from making an update on the event)

    private void sumAllCheckedAndNotify() {
        double sum = 0;
        for (int i = 0; i < checkedArr.length; i++) {
            if(checkedArr[i]) {
                sum += Double.parseDouble(catalogDatabases.get(i).getPriceItem());
            }
        }
        // pudate the listener
        listener.respond(sum, selectedCount);
    }
Rami Loiferman
  • 624
  • 4
  • 15
0

Store totalPrice inside adapter and add/subtract value based on CheckBox state like below:

class YourAdapter extends ... {

    double totalPrice = 0;

    ...

    @Override
    public void onBindViewHolder(@NonNull RecyclerHolder holder, int position) {

       holder.itemCheckBox.setChecked(catalogDatabases.get(position).isSelected());

       holder.itemCheckBox.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                double price = Double.parseDouble(catalogDatabases.get(position).getPriceItem());

                boolean isSelected = !catalogDatabases.get(position).isSelected();
                catalogDatabases.get(position).setSelected(isSelected);

                if (isSelected) {
                    totalPrice += price;
                } else {
                    totalPrice -= price;
                }

                holder.listener.respond(totalPrice);

                notifyDataSetChanged();
            }
        });
    }
}

Update your Model to hold checked/ unchecked state to persist data

class CatalogDatabase { //Assume this is your model class

    private boolean isSelected

    ....

    public boolean isSelected() {
        return isSelected;
    }

    public void setSelected(boolean selected) {
        isSelected = selected;
    }

    ....
}
Md. Asaduzzaman
  • 13,121
  • 2
  • 19
  • 34