notifyDataSetChanged和notifyDataSetInvalidated区别以及观察者模式的使用

 

notifydatasetinvalidated

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

源码爬的很开心,pompip原创

相关阅读

Javascript:history.go()和history.back()的用法与区

Javascript:history.go()和history.back()的用法与区别简单的说就是:go(-1):返回上一页,原页面表单中的内容会丢失;back():返回上一页

127.0.0.1和localhost和本机IP三者的区别

1,什么是环回地址??与127.0.0.1的区别呢??环回地址是主机用于向自身发送通信的一个特殊地址(也就是一个特殊的目的地址)。可以这么说:同一

健身中有氧运动和无氧运动是什么?它们有什么区别?

对于许多刚刚学习健身的朋友来说,往往在许多的学习资料中,都会看到这样的词语,例如“有氧运动”、“无氧运动”之类的。那么,这个有氧

interesting和interested的区别

1、interesting 表示使人感兴趣,interested 表示某人自己本身感兴趣。 2、一般情况下, interesting 指物,interested 指人。 3、

Servlet中request.getParameter和getParameterValues

Servlet中request.getParameter和getParameterValuesgetParameterNames三者区别 1.request.getParameter:获取前台表单单个元素na

发表评论