ListView 中包含 EditText,點擊 EditText 時 BaseAdapter.getView() 被重複調用,導致界面閃爍、數據重置等異常。
ListView 佈局重渲染機制:
getView() 重新綁定視圖getView() 實現不當:未正確使用 convertView 復用、未使用 ViewHolder 模式getView() 中被修改(如代碼中 vh.createDate.setText(chatMessage.getContent()) 疑似邏輯顛倒)android:descendantFocusability 控制焦點行為<ListView
android:id="@+id/listView1"
android:descendantFocusability="beforeDescendants"
android:layout_width="match_parent"
android:layout_height="match_parent" />
beforeDescendants:ListView 先獲取焦點,子 View 再獲取,減少重渲染afterDescendants:子 View 優先(默認)blocksDescendants:阻塞子 View 獲取焦點(ListView 不可編輯時用)<activity
android:name=".MainActivity"
android:windowSoftInputMode="adjustPan|stateHidden" />
adjustPan:窗口平移而非壓縮,避免 ListView 重新佈局stateHidden:默認隱藏軟鍵盤@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder vh;
if (convertView == null) {
convertView = inflater.inflate(layoutId, parent, false);
vh = new ViewHolder(convertView);
convertView.setTag(vh);
} else {
vh = (ViewHolder) convertView.getTag();
}
Msg msg = mDatas.get(position);
// 僅綁定數據,不修改數據源!
vh.createDate.setText(msg.getDateStr()); // 修正:顯示日期
vh.content.setText(msg.getContent()); // 修正:顯示內容
return convertView;
}
RecyclerView 強制 ViewHolder 模式notifyItemChanged(position, payload) 實現局部刷新vh.createDate.setText(chatMessage.getContent()); // 錯:日期欄顯示內容
vh.content.setText(chatMessage.getDateStr()); // 錯:內容欄顯示日期
應交換為:
vh.createDate.setText(chatMessage.getDateStr());
vh.content.setText(chatMessage.getContent());
點擊 EditText 觸發 getView() 是 ListView 重佈局機制導致。綜合採用 descendantFocusability、windowSoftInputMode=adjustPan、優化 getView() 復用邏輯、修正數據綁定錯誤,可徹底解決。長期建議遷移至 RecyclerView。