Android 學習之那些年我們遇到的BUG8:ArrayAdapter 直接使用 notifyDataSetChanged()無效

BUG:在使用AutoCompleteTextView時,用ArrayAdapter作爲適配器,刷新數據時使用notifyDataSetChanged()無效。

修改 ArrayList 然後調用 notifyDataSetChanged() 對於ArrayAdapter 沒有產生影響,裏面的數據並未發生改變,造成 notifyDataSetChanged() 無效

直接使用 ArrayAdapter 自帶的clear(),add(), insert() and remove() 等函數可解決。

原因:
查看 ArrayAdapter 的源碼發現,ArrayAdapter 在調用 notifyDataSetChanged() 時,並未將 ArrayList 數據的修改同步到 ArrayAdapter 內部。

@Override
public void notifyDataSetChanged() {
	super.notifyDataSetChanged();
	mNotifyOnChange = true;
}

而 add() 等函數則先將 ArrayList 數據的修改同步到 ArrayAdapter 內部,再調用父類的notifyDataSetChanged()

public void add(@Nullable T object) {
	synchronized (mLock) {
    	if (mOriginalValues != null) {
	    	mOriginalValues.add(object);
    	} else {
        mObjects.add(object);
		}
		mObjectsFromResources = false;
	}
	if (mNotifyOnChange) notifyDataSetChanged();
}

其中的 mNotifyOnChange 變量可通過調用 setNotifyOnChange(notifyOnChange) 方法設置爲 false,則再使用 add() 等函數時若要產生變化效果則需要手動調用notifyDataSetChanged() 方法。

/**
* Control whether methods that change the list ({@link #add}, {@link #addAll(Collection)},
* {@link #addAll(Object[])}, {@link #insert}, {@link #remove}, {@link #clear},
* {@link #sort(Comparator)}) automatically call {@link #notifyDataSetChanged}.  If set to
* false, caller must manually call notifyDataSetChanged() to have the changes
* reflected in the attached view.
*
* The default is true, and calling notifyDataSetChanged()
* resets the flag to true.
*
* @param notifyOnChange if true, modifications to the list will
*                       automatically call {@link
*                       #notifyDataSetChanged}
*/
public void setNotifyOnChange(boolean notifyOnChange) {
	mNotifyOnChange = notifyOnChange;
}

第一次嘗試分析 Android 源碼!如有錯誤,煩請指正。

發佈了57 篇原創文章 · 獲贊 25 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章