本文要讲的是当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导致了数据错乱。
本文的内容已全部结束,这次是小猿第一次写文章,有不足之处请各位大大多多指导。
网友评论