項(xiàng)目中有一個(gè)頁面實(shí)現(xiàn)的是用戶為教師打分的功能嘶是,頁面使用 RecyclerView 來實(shí)現(xiàn)的,由于這個(gè)功能一直沒有正式上線使用竿奏,所以接手之后我也沒有注意過這段代碼是否存在問題荠耽。在前段時(shí)間上線使用之后,今天用戶反應(yīng)說這個(gè)頁面存在 crash豺谈,遂檢查修復(fù)郑象。
發(fā)現(xiàn)只是一個(gè)簡(jiǎn)單的空指針錯(cuò)誤(原來負(fù)責(zé)項(xiàng)目的人對(duì)空指針的判斷已經(jīng)坑我若干次了...),修復(fù)之后進(jìn)行了簡(jiǎn)單的測(cè)試茬末,發(fā)現(xiàn)還存在這另一個(gè)問題:在 EditText 中修改分值后厂榛,如果滾動(dòng) RecyclerView 再次回到該處的時(shí)候,EditText 中的內(nèi)容被置為 0 了丽惭』髂蹋坑里有坑!這就很尷尬了吐根,這個(gè)項(xiàng)目的前任工程師真是挖了一個(gè)很大的坑啊正歼。
當(dāng)遇到這個(gè)問題的時(shí)候,我也有點(diǎn)一頭霧水拷橘,于是檢查代碼局义,其中與 EditText 的操作都是在 Adapter 中的,關(guān)鍵代碼如下所示:
@Override
public void onBindViewHolder(final ViewHolder holder, final int position) {
final AssessCheckListBean.CheckBean taskBean = dataList.get(position);
holder.tv_check_title.setText(taskBean.getTeachername());
holder.et_check_score.setText(taskBean.getTeacherscore() + "");
holder.et_check_score.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {}
@Override
public void afterTextChanged(Editable s) {
taskBean.setTeacherscore(holder.et_check_score.getText().toString());
}
});
}
可以看出是在 onBindViewHolder 中為 EditText 添加了一個(gè) TextWatcher冗疮,用來在用戶輸入后將數(shù)據(jù)取出寫入到 列表數(shù)據(jù)中萄唇。
乍一看這段代碼沒有什么問題,但實(shí)際上這里有一個(gè)很大的坑术幔。通過在 afterTextChanged 方法上增加 Log 記錄可以發(fā)現(xiàn)另萤,該方法會(huì)被多次的調(diào)用,并且在滑動(dòng)后最終結(jié)果變成 0 诅挑,其根本原因是因?yàn)?EditText 的重新繪制四敞!當(dāng)重繪之后 該回調(diào)函數(shù)沒有獲取到填充的數(shù)據(jù),從而導(dǎo)致了數(shù)值都被置為 0 了拔妥。
解決方法很簡(jiǎn)單忿危,我們只要在每次填充數(shù)據(jù)之前先移除 TextWatcher 監(jiān)聽器,然后為 EditText 填充數(shù)據(jù) 没龙,最后在為 EditText 添加 TextWatcher 監(jiān)聽器铺厨,代碼如下所示:
@Override
public void onBindViewHolder(final ViewHolder holder, final int position) {
final AssessCheckListBean.CheckBean taskBean = dataList.get(position);
holder.tv_check_title.setText(taskBean.getTeachername());
if (holder.et_check_score.getTag() instanceof TextWatcher) {
holder.et_check_score.removeTextChangedListener((TextWatcher) holder.et_check_score.getTag());
}
holder.et_check_score.setText(taskBean.getTeacherscore() + "");
TextWatcher watcher = new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {}
@Override
public void afterTextChanged(Editable s) {
taskBean.setTeacherscore(holder.et_check_score.getText().toString());
}
};
holder.et_check_score.addTextChangedListener(watcher);
holder.et_check_score.setTag(watcher);
}