需求:有一個清單,清單中有一個edittext(隻能輸整形),外部有一個整形變量Int,每次改變清單中其中一項的edittext的值時,外部的Int都會改變。
既然這樣,我們就需要對edittext進行addTextChangedListener監聽,一般做法是在afterTextChanged中對外部進行循環累加,但是想想,每一次你改變edittext都要進行一次時間複雜度為n的循環的話,想想就覺得這個算法很那啥,是以我想了另一個算法,每次改變其中一個item的值時,用總的值減去原item的edittext中的值加上item的edittext新輸入的值,這樣的複雜度為1,看着就很舒服。
但是這樣也引出了一個問題,就是今天要說的BUG
我要講的BUG是RecyclerView導緻資料錯亂的問題
重要事情說三遍
你想想,對于addTextChangedListener這個方法,你每次對edittext進行setText操作後都會調用這個方法,不巧的是recyclerview是複用容器,資料超出可用的容器時,會對edittext進行複用,也就是說,我們本身隻想在addTextChangedListener中去監聽手動改變edittext的情況,而recyclerview重複調用setText也會導緻預設調用addTextChangedListener而會産生嚴重的資料錯亂。
舉個栗子,對我的需求原本是做這樣的操作。
edtItem.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
// todo 擷取到edit改變前的數字
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改後的數字
String now = edtItem.getText().toString();
}
});
這樣拿到目前Item改變前的數字和改變後的數字,傳給外部(傳的做法我這沒寫,可以用觀察者),然後外部總int - befour + now 就能擷取到新的總數。
這邏輯看是完美,但是recyclerview幫你settext時,你的befour就是複用前的item中的數,而now就是新settext上去的數。
簡單來說,我們要的效果是手動修改editText時才進行int - befour + now步驟,而現在你光滑動就莫名其妙進行int - 複用前item的數 + 複用後item的數。
那我們就需要解決一個問題,隻有手動修改edittext時,才進行正确的操作,滑動時,不進行操作
其實我以前有說過reyclerview不能直接對它的容器進行操作(也就是viewholder),而應該對它的資料進行操作。是以這裡我們改成這樣的話,就不會受到滑動更新資料的影響。
edtItem.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
// todo 擷取到edit改變前的數字
String befour = data;
}
@Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
}
@Override
public void afterTextChanged(Editable editable) {
// todo 擷取到edit改後的數字
data = edtItem.getText().toString();
String now = data ;
}
});
data是adapter傳給viewholder的資料。這樣寫的話在beforeTextChanged方法中擷取的就不是複用前item的資料,而是目前的資料。是以你滑動時發現befour 和now 會是一樣,這時就不用進行更改總數的操作,而手動改變editText時befour 和now 是不一樣的。
總結
可能你看不懂我的需求和例子,說明你沒碰到過這樣的情況(清單的edittext影響外部某個狀态),我也不太好解釋,但是你基本會碰到過資料錯亂的情況,這就是我要說的。
在RecyclerView中,不管你要做什麼操作,不要直接對容器(ViewHolder)操作,而是對資料進行操作。
補充一點java的常識
如果你傳的是對象的話,這裡對形參的改變,實參也會變,但是傳基本資料類型的話,你變形參是不會影響實參的,是以不管有多少個資料,在viewholder中最後應該傳入對象而不是基本資料類型.