關於RecyclerView中包含Edittext的問題的幾種解決方法

最近項目中有這樣一個需求:購物車列表中的數量能夠手動經過輸入修改。經過需求判斷,購物車是一個列表,列表中包含有Edittext。那麼問題來了, recyclerview中包含edittext在滾動時會發生數據混亂的問題,之因此數據混亂就是由於Recyclerview的複用致使的。針對這個問題記錄了幾種方法來進行解決。bash

注:demo引用了BaseRecyclerViewAdapteHelper,故adapter繼承了BaseQuickAdapter,此註釋是爲了防止沒有看懂 convert(BaseViewHolder helper, EdittextInRecyclerViewOfBean item)這個方法ide

方法一:強制的停用Recyclerview的複用。

這種方法不推薦,recyclerview最大的好處之一就是複用,若是中止複用,當數據量很大,或者條目中有大圖的時候會佔用很大的內存,會形成卡頓或者崩潰。ui

helper.setIsRecyclable(false);
複製代碼

方法二:經過監聽焦點來添加或移除Edittext的TextChangedListener來解決

在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);
            }
        }
    });
}
複製代碼

方法三:經過view的setTag()方法解決

每次填充數據以前先移除 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);
}
複製代碼

方法四:爲每一個edittext的綁定位置

當相應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()));
            }
        }
    }
}
複製代碼
相關文章
相關標籤/搜索