Reputation: 319
I have a ViewHolder:
import android.widget.EditText;
import android.widget.TextView;
public class ListViewHolder {
TextView productName;
EditText productStock;
}
And my ListAdapter (listProducts is an ArrayList of Product objects):
public Product getItem(int position){
return listProducts.get(position);
}
public View getView(final int position, View convertView, ViewGroup parent){
View row;
final ListViewHolder listViewHolder;
if(convertView == null){
LayoutInflater layoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
row = layoutInflater.inflate(R.layout.set_stock_listview,parent,false);
listViewHolder = new ListViewHolder();
listViewHolder.productName = (TextView) row.findViewById(R.id.productName);
listViewHolder.productStock = (EditText) row.findViewById(R.id.productStock);
row.setTag(listViewHolder);
}
else{
row = convertView;
listViewHolder = (ListViewHolder) row.getTag();
}
final Product product = getItem(position);
if(product.getDesiredQuantity()>0){
listViewHolder.productStock.setText(String.valueOf(product.getDesiredQuantity()));
}
listViewHolder.productName.setText(product.getName()+":");
listViewHolder.productStock.setInputType(InputType.TYPE_CLASS_NUMBER);
listViewHolder.productStock.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
}
@Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
}
@Override
public void afterTextChanged(Editable editable) {
product.setDesiredQuantity(Integer.valueOf(editable.toString()));
}
});
return row;
}
However when scrolling through the list, the value of the EditText duplicates to many of the other rows. It looks like it must be updating the other Product objects also but I haven't been able to find the issue, any ideas?
Upvotes: 1
Views: 239
Reputation: 54204
The problem is a combination of the fact that views can be recycled (via the convertView
argument) and the fact that TextView
only allows you to add a TextWatcher
. In the code you've posted, every time getView()
is called with a non-null convertView
, you will create an additional TextWatcher
and assign it to productStock
... and the previous watchers will remain in place updating the previously-bound product
.
You have to remove the existing TextWatcher
if it has one. I recommend using the ListViewHolder
to accomplish this.
public class ListViewHolder {
TextView productName;
EditText productStock;
TextWatcher productStockWatcher;
}
And then change this:
listViewHolder.productStock.addTextChangedListener(new TextWatcher() { ... });
To this:
if (listViewHolder.productStockWatcher != null) {
listViewHolder.productStock.removeTextChangedListener(productStockWatcher);
}
listViewHolder.productStockWatcher = new TextWatcher() { ... };
listViewHolder.productStock.addTextChangedListener(listViewHolder.productStockWatcher);
Upvotes: 2