Solution 1 :
Its because of nature of RecyclerView.
RecyclerView tries to reuse (recycle) already drawn items(viewHolders) when drawing new items.
Since you get input
from view which is recycled, it already has a value and continues to increase/decrease from that value.
All you need to do is to holder.quantity.setText(some default value);
in onBindView
method OR store the input in your model.
Problem :
The problem is in the recyclerview, if the view in one of the items is changed then the view gets changed in another item. And it changes specifically in the 8th position after the position of the actual item that is to be changed. Say, I change the quantity or price of the item in position 1 then the quantity or price is also gets changed in position 1 + 8 = 9th item. I can’t figure out why this is occurring since I’m simply changing the view in the viewholder position. If anyone faced this kind of problem or has any solution it will be helpful. Thank you.
RecyclerView Layout:
<androidx.recyclerview.widget.RecyclerView
android_id="@+id/product_recyclerview"
android_layout_width="match_parent"
android_layout_height="wrap_content"
android_layout_marginTop="@dimen/_10sdp"
android_visibility="visible"/>
Adapter:
public class ProductAdapter extends RecyclerView.Adapter<ProductAdapter.MyViewHolder> {
private List<ProductItem> productItemList;
private Context context;
private ExpenseActivityContract.Presenter presenter;
public ProductAdapter(Context context, ExpenseActivityContract.Presenter presenter, List<ProductItem> productItemList) {
this.productItemList = productItemList;
this.presenter = presenter;
this.context = context;
}
public class MyViewHolder extends RecyclerView.ViewHolder {
ImageView productImage;
TextView productName, add;
EditText quantity, price;
ImageButton plus, minus;
public MyViewHolder(View v) {
super(v);
productImage = v.findViewById(R.id.product_image);
productName = v.findViewById(R.id.product_name);
add = v.findViewById(R.id.add_product_btn);
quantity = v.findViewById(R.id.quantity_input);
price = v.findViewById(R.id.product_price_input);
plus = v.findViewById(R.id.plus_qnty_btn);
minus = v.findViewById(R.id.minus_qnty_btn);
}
}
@Override
public ProductAdapter.MyViewHolder onCreateViewHolder(ViewGroup parent,
int viewType) {
View v = LayoutInflater.from(parent.getContext())
.inflate(R.layout.product_item_layout, parent, false);
MyViewHolder vh = new MyViewHolder(v);
return vh;
}
@Override
public long getItemId(int position) {
return super.getItemId(position);
}
@Override
public int getItemViewType(int position) {
return super.getItemViewType(position);
}
@Override
public void onBindViewHolder(final MyViewHolder holder, final int position) {
holder.productName.setText(productItemList.get(position).getProductName());
holder.plus.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String input = holder.quantity.getText().toString();
if(TextUtils.isEmpty(input)) {
holder.quantity.setText("1");
}
else {
double qnty = Double.parseDouble(input);
qnty = qnty + 1.00;
holder.quantity.setText(String.valueOf(qnty));
}
}
});
holder.minus.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String input = holder.quantity.getText().toString();
if(TextUtils.isEmpty(input)) {
holder.quantity.setText("0");
}
else {
double qnty = Double.parseDouble(input);
if(qnty > 1.0) {
qnty = qnty - 1.00;
holder.quantity.setText(String.valueOf(qnty));
}
else if(qnty >= 0.0 && qnty <= 1.0) {
holder.quantity.setText("0");
}
}
}
});
}
@Override
public int getItemCount() {
return productItemList.size();
}
}
Comments
Comment posted by RoShan Shan
Could I see your code calling changing/notifying the adapter?
Comment posted by Shafiul Islam Sajib
@RoShanShan I am not changing/notifying the adapter. I am using the
Comment posted by RoShan Shan
This is not the way to change your item ViewHolder inside RecyclerView. You should change the data and after that, you call
Comment posted by Shafiul Islam Sajib
@RoShanShan Yes. You are right. I implemented the adapter according to that. It’s working now.
Comment posted by Shafiul Islam Sajib
Okay, I get the point. Since it reuses the viewholder, I will have to implement some logic according to that.
Comment posted by ali73
@ShafiulIslamSajib I edited my answer and tried to explain better.
Comment posted by Shafiul Islam Sajib
I changed the code according to your suggestion. Instead of changing the view directly, I changed the item values and used