关于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()));
            }
        }
    }
}
复制代码
相关文章
相关标签/搜索