notifyDataSetChanged和notifyDataSetInvalidated区别以及观察者模式的使用
看Observer和Observable的时候,爬了下Listview的源码,研究了下ANdroid中用到的观察者模式
两个方法
相同点
当改变Adapter数据后,调用两个方法都会刷新视图
不同点
notifyDataSetChanged会保存刷新前的状态,比如Listview滑动的位置;
notifyDataSetInvalidated会清空所有信息,重新布局,位置会到最上方;
源码
源码位于AdapterView中的内部类AdapterDataSetObserver (观察者)
class AdapterDataSetObserver extends DataSetObserver {
private Parcelable mInstanceState = null;
@Override
public void onChanged() {
mDataChanged = true;
mOldItemCount = mItemCount;
mItemCount = getAdapter().getCount();
// Detect the case where a cursor that was previously invalidated has
// been repopulated with new data.
if (AdapterView.this.getAdapter().hasStableIds() && mInstanceState != null
&& mOldItemCount == 0 && mItemCount > 0) {
AdapterView.this.onRestoreInstanceState(mInstanceState);
mInstanceState = null;
} else {
rememberSyncState();
}
checkFocus();
requestLayout();
}
@Override
public void onInvalidated() {
mDataChanged = true;
if (AdapterView.this.getAdapter().hasStableIds()) {
// Remember the current state for the case where our hosting activity is being
// stopped and later restarted
mInstanceState = AdapterView.this.onSaveInstanceState();
}
// Data is invalid so we should reset our state
mOldItemCount = mItemCount;
mItemCount = 0;
mSelectedPosition = INVALID_POSITION;
mSelectedRowId = INVALID_ROW_ID;
mNextSelectedPosition = INVALID_POSITION;
mNextSelectedRowId = INVALID_ROW_ID;
mNeedSync = false;
checkFocus();
requestLayout();
}
public void clearSavedState() {
mInstanceState = null;
}
}
源码说明
notifyDataSetChanged
当调用
notifyDataSetChanged
,通过观察中会调用到onChanged
,
其中AdapterView.this.onRestoreInstanceState(mInstanceState);
保存了当前Listview布局信息;
最终调用父类 View 中`requestLayout()`重新布局;当调用notifyDataSetInvalidated , onInvalidated会被调用,布局信息被初始化,最终调用requestLayout,布局恢复初始状态。
使用场景
如果需要adapter丢弃用户操作后的信息,可以调用
notifyDataSetInvalidated
,让listview初始化;反之则调用notifyDataSetChanged,让当前页面的位置,选中状态等信息保持不变;
当然最终使用场景可以分别调用两种方法实验。
观察者模式在Listview中的使用
Android 没有使用java提供的Observable ,而是使用Android源码中android.database.Observable<>
观察者模式的具体实现
- 基类 Observable中 registerObserver unregisterObserver提供添加和删除观察者的方法;
- 子类 DataSetObservable继承Observable,提供notifyChanged 通知mObserver.onChanged(),提供notifyInvalidated调用 mObserver.onInvalidated;
- 观察者 DataSetObserver 中提供了 onChanged和onInvalidated两个未实现的方法;
- Listview系列view的基类adapterView中提供了内部类AdapterDataSetObserver 继承DataSetObserver 实现了DataSetObserver的两个方法,用了操作ListView不同的状态;
具体实现
- BaseAdapter中注册mDataSetObservable 被观察者,以及通知观察者
DataSetObservable mDataSetObservable = new DataSetObservable();
public void registerDataSetObserver(DataSetObserver observer) {
mDataSetObservable.registerObserver(observer);
}
public void unregisterDataSetObserver(DataSetObserver observer) {
mDataSetObservable.unregisterObserver(observer);
}
public void unregisterDataSetObserver(DataSetObserver observer) {
mDataSetObservable.unregisterObserver(observer);
}
public void notifyDataSetChanged() {
mDataSetObservable.notifyChanged();
}
- AbsListView中注册和解绑
@Override
protected void onAttachedToWindow() {
mDataSetObserver = new AdapterDataSetObserver();
mAdapter.registerDataSetObserver(mDataSetObserver);
}
@Override
protected void onDetachedFromWindow() {
mAdapter.unregisterDataSetObserver(mDataSetObserver);
mDataSetObserver = null;
}
- 在加上文章最上面的源码,一套流程over