本文要講的是當(dāng)Adapter復(fù)用引起的EditText數(shù)據(jù)錯(cuò)誤的解決方法。
在開(kāi)始講解決方法前,先向大家推薦一個(gè)github上的工具BaseRecyclerViewAdapterHelper官方指南、BaseRecyclerViewAdapterHelper的github地址。
這個(gè)工具類可以大幅減少你編寫(xiě)Adapter的代碼量,而且能實(shí)現(xiàn)三級(jí)樹(shù)形結(jié)構(gòu)。
本文的解決方法也是基于這個(gè)工具類,廢話不多說(shuō)進(jìn)入正題。
很多時(shí)候我們做APP的時(shí)候都會(huì)遇到類似表單提交的需求
我需要在用戶每次編輯簽收數(shù)時(shí)記錄商品及其對(duì)應(yīng)的簽收數(shù),為此我們會(huì)創(chuàng)建一個(gè)Map記錄它們之間的對(duì)應(yīng)關(guān)系,然后給每個(gè)EditText加上TextWatch,當(dāng)用戶編輯時(shí)改變Map中對(duì)應(yīng)的數(shù)值,當(dāng)我們商品數(shù)很少的時(shí)候(15個(gè)以內(nèi)),我們這種做法就已經(jīng)完成了需求,但事情并不會(huì)這么簡(jiǎn)單,如果超過(guò)15個(gè)的時(shí)候,你就會(huì)發(fā)現(xiàn)當(dāng)你修改第一個(gè)商品的簽收數(shù)時(shí),第16個(gè)商品的簽收數(shù)也跟著改變。
這是因?yàn)閂iewHolder復(fù)用導(dǎo)致,在程序中第一個(gè)商品的ViewHolder和第16個(gè)是同一個(gè),當(dāng)我們?yōu)檫@個(gè)ViewHolder添加TextWatch時(shí),這個(gè)ViewHolder是同時(shí)存在兩個(gè)TextWatch,這就是導(dǎo)致數(shù)據(jù)錯(cuò)誤的原因。
解決方案直接上代碼
//保存所有EditText的id
private ArrayList<Integer> edtIds = new ArrayList<>();
//保存所有EditText對(duì)應(yīng)的TextWatcher
private ArrayMap<String, TextWatcher> textWatcherArrayMap = new ArrayMap<>();
/**
* 每次添加TextWatch時(shí)調(diào)用這個(gè)方法
* @param id 當(dāng)前EditText的id
* @param adapterPosition 當(dāng)前列表項(xiàng)的位置
* @param textWatcher 當(dāng)前EditText對(duì)應(yīng)的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);
}
//當(dāng)適配器創(chuàng)建的view(即列表項(xiàng)view)被窗口分離(即滑動(dòng)離開(kāi)了當(dāng)前窗口界面)就會(huì)被調(diào)用
@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();
//當(dāng)窗口與列表項(xiàng)分離時(shí),刪除對(duì)應(yīng)的TextWatch
editText.removeTextChangedListener(textWatcherArrayMap.get(name));
}
}
}
}
以上代碼直接貼到你的自定義Adapter里面就可以了,當(dāng)你每次給EditText添加TextWatch時(shí)調(diào)用一下addTextWatcher這個(gè)方法,問(wèn)題就輕松解決了,其實(shí)原理很簡(jiǎn)單,就是每次給EditText添加TextWatch時(shí)記錄起來(lái),當(dāng)用戶滑動(dòng)當(dāng)前頁(yè)面,看不到這個(gè)列表項(xiàng)時(shí),就會(huì)自動(dòng)調(diào)用onViewDetachedFromWindow這個(gè)方法,每次調(diào)用onViewDetachedFromWindow這個(gè)方法時(shí)自動(dòng)解除之前綁定TextWatch,這樣就不會(huì)存在多個(gè)TextWatch導(dǎo)致了數(shù)據(jù)錯(cuò)亂。
本文的內(nèi)容已全部結(jié)束,這次是小猿第一次寫(xiě)文章,有不足之處請(qǐng)各位大大多多指導(dǎo)。