欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Android 学习之那些年我们遇到的BUG8:ArrayAdapter 直接使用 notifyDataSetChanged()无效

程序员文章站 2022-05-25 23:46:27
...

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 源码!如有错误,烦请指正。