RecyclerView中監(jiān)聽(tīng)EditText變化的BUG的解決方法
需求:有一個(gè)列表,列表中有一個(gè)edittext(只能輸整形),外部有一個(gè)整形變量Int,每次改變列表中其中一項(xiàng)的edittext的值時(shí),外部的Int都會(huì)改變。
既然這樣,我們就需要對(duì)edittext進(jìn)行addTextChangedListener監(jiān)聽(tīng),一般做法是在afterTextChanged中對(duì)外部進(jìn)行循環(huán)累加,但是想想,每一次你改變edittext都要進(jìn)行一次時(shí)間復(fù)雜度為n的循環(huán)的話,想想就覺(jué)得這個(gè)算法很那啥,所以我想了另一個(gè)算法,每次改變其中一個(gè)item的值時(shí),用總的值減去原item的edittext中的值加上item的edittext新輸入的值,這樣的復(fù)雜度為1,看著就很舒服。
但是這樣也引出了一個(gè)問(wèn)題,就是今天要說(shuō)的BUG
我要講的BUG是RecyclerView導(dǎo)致數(shù)據(jù)錯(cuò)亂的問(wèn)題
我要講的BUG是RecyclerView導(dǎo)致數(shù)據(jù)錯(cuò)亂的問(wèn)題
我要講的BUG是RecyclerView導(dǎo)致數(shù)據(jù)錯(cuò)亂的問(wèn)題
重要事情說(shuō)三遍
你想想,對(duì)于addTextChangedListener這個(gè)方法,你每次對(duì)edittext進(jìn)行setText操作后都會(huì)調(diào)用這個(gè)方法,不巧的是recyclerview是復(fù)用容器,數(shù)據(jù)超出可用的容器時(shí),會(huì)對(duì)edittext進(jìn)行復(fù)用,也就是說(shuō),我們本身只想在addTextChangedListener中去監(jiān)聽(tīng)手動(dòng)改變edittext的情況,而recyclerview重復(fù)調(diào)用setText也會(huì)導(dǎo)致默認(rèn)調(diào)用addTextChangedListener而會(huì)產(chǎn)生嚴(yán)重的數(shù)據(jù)錯(cuò)亂。
舉個(gè)栗子,對(duì)我的需求原本是做這樣的操作。
edtItem.addTextChangedListener(new TextWatcher() { @Override public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) { // todo 獲取到edit改變前的數(shù)字 String befour = edtItem.getText().toString(); } @Override public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) { } @Override public void afterTextChanged(Editable editable) { // todo 獲取到edit改后的數(shù)字 String now = edtItem.getText().toString(); } });
這樣拿到當(dāng)前Item改變前的數(shù)字和改變后的數(shù)字,傳給外部(傳的做法我這沒(méi)寫(xiě),可以用觀察者),然后外部總int - befour + now 就能獲取到新的總數(shù)。
這邏輯看是完美,但是recyclerview幫你settext時(shí),你的befour就是復(fù)用前的item中的數(shù),而now就是新settext上去的數(shù)。
簡(jiǎn)單來(lái)說(shuō),我們要的效果是手動(dòng)修改editText時(shí)才進(jìn)行int - befour + now步驟,而現(xiàn)在你光滑動(dòng)就莫名其妙進(jìn)行int - 復(fù)用前item的數(shù) + 復(fù)用后item的數(shù)。
那我們就需要解決一個(gè)問(wèn)題,只有手動(dòng)修改edittext時(shí),才進(jìn)行正確的操作,滑動(dòng)時(shí),不進(jìn)行操作
其實(shí)我以前有說(shuō)過(guò)reyclerview不能直接對(duì)它的容器進(jìn)行操作(也就是viewholder),而應(yīng)該對(duì)它的數(shù)據(jù)進(jìn)行操作。所以這里我們改成這樣的話,就不會(huì)受到滑動(dòng)更新數(shù)據(jù)的影響。
edtItem.addTextChangedListener(new TextWatcher() { @Override public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) { // todo 獲取到edit改變前的數(shù)字 String befour = data; } @Override public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) { } @Override public void afterTextChanged(Editable editable) { // todo 獲取到edit改后的數(shù)字 data = edtItem.getText().toString(); String now = data ; } });
data是adapter傳給viewholder的數(shù)據(jù)。這樣寫(xiě)的話在beforeTextChanged方法中獲取的就不是復(fù)用前item的數(shù)據(jù),而是當(dāng)前的數(shù)據(jù)。所以你滑動(dòng)時(shí)發(fā)現(xiàn)befour 和now 會(huì)是一樣,這時(shí)就不用進(jìn)行更改總數(shù)的操作,而手動(dòng)改變editText時(shí)befour 和now 是不一樣的。
總結(jié)
可能你看不懂我的需求和例子,說(shuō)明你沒(méi)碰到過(guò)這樣的情況(列表的edittext影響外部某個(gè)狀態(tài)),我也不太好解釋?zhuān)悄慊緯?huì)碰到過(guò)數(shù)據(jù)錯(cuò)亂的情況,這就是我要說(shuō)的。
在RecyclerView中,不管你要做什么操作,不要直接對(duì)容器(ViewHolder)操作,而是對(duì)數(shù)據(jù)進(jìn)行操作。
補(bǔ)充一點(diǎn)java的常識(shí)
如果你傳的是對(duì)象的話,這里對(duì)形參的改變,實(shí)參也會(huì)變,但是傳基本數(shù)據(jù)類(lèi)型的話,你變形參是不會(huì)影響實(shí)參的,所以不管有多少個(gè)數(shù)據(jù),在viewholder中最后應(yīng)該傳入對(duì)象而不是基本數(shù)據(jù)類(lèi)型.
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- Android編程實(shí)現(xiàn)實(shí)時(shí)監(jiān)聽(tīng)EditText文本輸入的方法
- Android編程實(shí)現(xiàn)EditText字?jǐn)?shù)監(jiān)聽(tīng)并顯示的方法
- EditText監(jiān)聽(tīng)方法,實(shí)時(shí)的判斷輸入多少字符
- Android開(kāi)發(fā)中給EditText控件添加TextWatcher監(jiān)聽(tīng)實(shí)現(xiàn)對(duì)輸入字?jǐn)?shù)的限制(推薦)
- Android EditText 實(shí)現(xiàn)監(jiān)聽(tīng)實(shí)例
- 全面解析Android中對(duì)EditText輸入實(shí)現(xiàn)監(jiān)聽(tīng)的方法
- Android編程實(shí)現(xiàn)監(jiān)聽(tīng)EditText變化的方法
相關(guān)文章
Android開(kāi)發(fā)Input系統(tǒng)觸摸事件分發(fā)
這篇文章主要為大家介紹了Android開(kāi)發(fā)Input系統(tǒng)觸摸事件分發(fā)示例解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-03-03Android開(kāi)發(fā)實(shí)現(xiàn)的保存圖片到相冊(cè)功能示例
這篇文章主要介紹了Android開(kāi)發(fā)實(shí)現(xiàn)的保存圖片到相冊(cè)功能,結(jié)合實(shí)例形式分析了Android圖片命名、保存、權(quán)限控制等相關(guān)操作技巧,需要的朋友可以參考下2019-03-03Android通訊錄開(kāi)發(fā)之刪除功能的實(shí)現(xiàn)方法
這篇文章主要介紹了Android通訊錄開(kāi)發(fā)之刪除功能的實(shí)現(xiàn)方法,有需要的朋友可以參考一下2014-01-01Android自定義View實(shí)現(xiàn)氣泡動(dòng)畫(huà)
這篇文章主要為大家詳細(xì)介紹了Android自定義View實(shí)現(xiàn)氣泡動(dòng)畫(huà),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-04-04Android開(kāi)發(fā)中LayoutInflater用法詳解
這篇文章主要介紹了Android開(kāi)發(fā)中LayoutInflater用法,結(jié)合實(shí)例形式分析了LayoutInflater類(lèi)的功能、作用、使用方法及相關(guān)注意事項(xiàng),需要的朋友可以參考下2016-08-08Android 自定義彈出菜單和對(duì)話框功能實(shí)例代碼
Android 開(kāi)發(fā)當(dāng)中,可能會(huì)存在許多自定義布局的需求,比如自定義彈出菜單(popupWindow),以及自定義對(duì)話框(Dialog)。下面通過(guò)本文給大家介紹Android 自定義彈出菜單和對(duì)話框功能實(shí)例代碼,感興趣的朋友一起看看吧2017-08-08android通過(guò)藍(lán)牙接收文件打開(kāi)時(shí)無(wú)法自動(dòng)選擇合適的應(yīng)用程序
android 通過(guò)藍(lán)牙接收文件,從歷史傳輸記錄打開(kāi),無(wú)法自動(dòng)選擇合適的應(yīng)用程序,比如video player打開(kāi).3gp、.mp4文件等等2013-06-06