Adapter復(fù)用引起的EditText數(shù)據(jù)錯(cuò)誤

本文要講的是當(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ì)遇到類似表單提交的需求

image

我需要在用戶每次編輯簽收數(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)。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 179,167評(píng)論 25 708
  • 用兩張圖告訴你,為什么你的 App 會(huì)卡頓? - Android - 掘金 Cover 有什么料? 從這篇文章中你...
    hw1212閱讀 14,041評(píng)論 2 59
  • 【Android 控件 RecyclerView】 概述 RecyclerView是什么 從Android 5.0...
    Rtia閱讀 308,464評(píng)論 27 440
  • 最近晚上經(jīng)常帶葵葵拉鏈,其實(shí)應(yīng)該是葵葵帶著我們拉鏈,因?yàn)樗袘?zhàn)車(滑板車),我和他爸就靠?jī)蓷l腿??钒职郑易房?..
    蘇田田閱讀 411評(píng)論 1 1
  • PlayerPrefs // 保存玩家數(shù)據(jù) PlayerPrefs.SetString(LoginName, _n...
    fooliker閱讀 309評(píng)論 0 0

友情鏈接更多精彩內(nèi)容