最近項目中有這樣一個需求:購物車列表中的數量能夠手動經過輸入修改。經過需求判斷,購物車是一個列表,列表中包含有Edittext。那麼問題來了, recyclerview中包含edittext在滾動時會發生數據混亂的問題,之因此數據混亂就是由於Recyclerview的複用致使的。針對這個問題記錄了幾種方法來進行解決。bash
注:demo引用了BaseRecyclerViewAdapteHelper,故adapter繼承了BaseQuickAdapter,此註釋是爲了防止沒有看懂 convert(BaseViewHolder helper, EdittextInRecyclerViewOfBean item)這個方法ide
這種方法不推薦,recyclerview最大的好處之一就是複用,若是中止複用,當數據量很大,或者條目中有大圖的時候會佔用很大的內存,會形成卡頓或者崩潰。ui
helper.setIsRecyclable(false);
複製代碼
在onBindViewHolder()中經過在適當的時機添加或移除Edittext的TextChangedListener來處理數據錯亂的問題。這個適當的時機就是選在Edittext得到焦點的時候添加監聽器,失去焦點的時候再移除監聽器,這樣能夠保證數據的正確性。this
@Override
protected void convert(BaseViewHolder helper, EdittextInRecyclerViewOfBean item) {
EditText editText = helper.getView(R.id.et);
editText.setText(item.getNum() + "");
TextWatcher textWatcher = new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
@Override
public void afterTextChanged(Editable s) {
//這裏處理數據
if (TextUtils.isEmpty(s.toString())) {
item.setNum(0);
} else {
item.setNum(Integer.parseInt(s.toString()));
}
}
};
editText.setOnFocusChangeListener(new View.OnFocusChangeListener() {
@Override
public void onFocusChange(View v, boolean hasFocus) {
if (hasFocus){
editText.addTextChangedListener(textWatcher);
}else {
editText.removeTextChangedListener(textWatcher);
}
}
});
}
複製代碼
每次填充數據以前先移除 TextWatcher 監聽器,而後爲 EditText 填充數據 ,最後在爲 EditText 添加 TextWatcher 監聽器。spa
@Override
protected void convert(BaseViewHolder helper, EdittextInRecyclerViewOfBean item) {
TextWatcher textWatcher = new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
@Override
public void afterTextChanged(Editable s) {
if (TextUtils.isEmpty(s.toString())) {
item.setNum(0);
} else {
item.setNum(Integer.parseInt(s.toString()));
}
}
};
EditText editText = helper.getView(R.id.et);
//爲了不TextWatcher在調用settext()時被調用,提早將它移除
if (editText.getTag() instanceof TextWatcher) {
editText.removeTextChangedListener((TextWatcher) editText.getTag());
}
editText.setText(item.getNum() + "");
//從新添加上TextWatcher監聽
editText.addTextChangedListener(textWatcher);
//將TextWatcher綁定到EditText
editText.setTag(textWatcher);
}
複製代碼
當相應position位置上的edittext發生變化時,對應的TextWatcher進行監聽並修改相應position的數據code
public class EditTextInRecyclerViewAdapter extends RecyclerView.Adapter {
private List<EdittextInRecyclerViewOfBean> mList = new ArrayList<>();
public void setData(List<EdittextInRecyclerViewOfBean> list) {
this.mList = list;
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_edittext, parent, false);
return new ViewHolder(v, new ITextWatcher());
}
@Override
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
ViewHolder viewHolder = (ViewHolder) holder;
viewHolder.mITextWatcher.bindPosition(position);
viewHolder.mEditText.setText(mList.get(position).getNum()+"");
}
@Override
public int getItemCount() {
return mList.size();
}
class ViewHolder extends RecyclerView.ViewHolder {
EditText mEditText;
ITextWatcher mITextWatcher;
private ViewHolder(View v, ITextWatcher watcher) {
super(v);
this.mEditText = v.findViewById(R.id.et);
this.mITextWatcher = watcher;
this.mEditText.addTextChangedListener(watcher);
}
}
class ITextWatcher implements TextWatcher {
private int position;
private void bindPosition(int position) {
this.position = position;
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
@Override
public void afterTextChanged(Editable s) {
if (TextUtils.isEmpty(s.toString())) {
mList.get(position).setNum(0);
} else {
mList.get(position).setNum(Integer.parseInt(s.toString()));
}
}
}
}
複製代碼