美文网首页
Adapter复用引起的EditText数据错误

Adapter复用引起的EditText数据错误

作者: Java全栈攻城狮 | 来源:发表于2018-11-03 10:23 被阅读0次

    本文要讲的是当Adapter复用引起的EditText数据错误的解决方法。

    在开始讲解决方法前,先向大家推荐一个github上的工具BaseRecyclerViewAdapterHelper官方指南BaseRecyclerViewAdapterHelper的github地址

    这个工具类可以大幅减少你编写Adapter的代码量,而且能实现三级树形结构。

    本文的解决方法也是基于这个工具类,废话不多说进入正题。

    很多时候我们做APP的时候都会遇到类似表单提交的需求

    image

    我需要在用户每次编辑签收数时记录商品及其对应的签收数,为此我们会创建一个Map记录它们之间的对应关系,然后给每个EditText加上TextWatch,当用户编辑时改变Map中对应的数值,当我们商品数很少的时候(15个以内),我们这种做法就已经完成了需求,但事情并不会这么简单,如果超过15个的时候,你就会发现当你修改第一个商品的签收数时,第16个商品的签收数也跟着改变。

    这是因为ViewHolder复用导致,在程序中第一个商品的ViewHolder和第16个是同一个,当我们为这个ViewHolder添加TextWatch时,这个ViewHolder是同时存在两个TextWatch,这就是导致数据错误的原因。

    解决方案直接上代码

    //保存所有EditText的id
    private ArrayList<Integer> edtIds = new ArrayList<>();
    //保存所有EditText对应的TextWatcher
    private ArrayMap<String, TextWatcher> textWatcherArrayMap = new ArrayMap<>();
    
    /**
     * 每次添加TextWatch时调用这个方法
     * @param id                 当前EditText的id
     * @param adapterPosition  当前列表项的位置
     * @param textWatcher       当前EditText对应的TextWatcher
     */
    protected void addTextWatcher(@IdRes int id, int adapterPosition, TextWatcher textWatcher) {
        if (edtIds.indexOf(id) < 0) {
            edtIds.add(id);
        }
        String name = id + "/" + adapterPosition;
        textWatcherArrayMap.put(name, textWatcher);
    }
    
    //当适配器创建的view(即列表项view)被窗口分离(即滑动离开了当前窗口界面)就会被调用
    @Override
    public void onViewDetachedFromWindow(@NonNull MulitpleViewHolder holder) {
        super.onViewDetachedFromWindow(holder);
        int adapterPosition = holder.getAdapterPosition();
        for (int id : edtIds) {
            String name = id + "/" + adapterPosition;
            View view = holder.getView(id);
            if (view instanceof EditText) {
                EditText editText = holder.getView(id);
                if (editText != null) {
                    editText.clearFocus();
                    //当窗口与列表项分离时,删除对应的TextWatch
                    editText.removeTextChangedListener(textWatcherArrayMap.get(name));
                }
            }
        }
    }
    

    以上代码直接贴到你的自定义Adapter里面就可以了,当你每次给EditText添加TextWatch时调用一下addTextWatcher这个方法,问题就轻松解决了,其实原理很简单,就是每次给EditText添加TextWatch时记录起来,当用户滑动当前页面,看不到这个列表项时,就会自动调用onViewDetachedFromWindow这个方法,每次调用onViewDetachedFromWindow这个方法时自动解除之前绑定TextWatch,这样就不会存在多个TextWatch导致了数据错乱。
    本文的内容已全部结束,这次是小猿第一次写文章,有不足之处请各位大大多多指导。

    相关文章

      网友评论

          本文标题:Adapter复用引起的EditText数据错误

          本文链接:https://www.haomeiwen.com/subject/hzfkxqtx.html