Cursor,CursorAdapter中的观察者模式解析

Cursor , CursorAdapter 配合 ListView 一起使用,当数据发生改变的时候,可以实现列表数据自动刷新。现在介绍一下内中原理。

1 、 ContentProvider 与 Cursor 之间的关系。

我们使用 Uri 向 ContentProvider 发起一个 query 请求用来得到 Cursor 对象。但在 cursor 对象返回之前,我们会给 cursor 对象执行 setNotificationUri ()方法。

publicCursorquery(Uriuri,String[] projection,String selection,String[]selectionArgs,String sortOrder){
SQLiteDatabasedb = mOpenHelper.getReadableDatabase();
Cursorcursor = null;
switch(URI_MATCHER.match(uri)){
caseXXX:
break;
caseXXX:
break;
..
default:
break;
}
if(cursor!= null){
cursor.setNotificationUri(getContext().getContentResolver(),XXX.CONTENT_URI);
}
returncursor;
}

在 setNotificationUri 方法中执行内容如下:

类: AbstractCursor.java

publicvoidsetNotificationUri(ContentResolver cr, Uri notifyUri) {
synchronized(mSelfObserverLock){
mNotifyUri= notifyUri;
mContentResolver= cr;
if(mSelfObserver!= null){
mContentResolver.unregisterContentObserver(mSelfObserver);
}
mSelfObserver= newSelfContentObserver(this);
mContentResolver.registerContentObserver(mNotifyUri,true,mSelfObserver);
mSelfObserverRegistered= true;
}
}

在这个方法内部,首先检查 mSelfObserver 是否为 null ,如果不为 null, 解除mSelfObserver 对 uri 的监听。然后重新使用 new 进行实例化一个 mSelfObserver 对象, mSelfObserver 继承自 ContentObserver 。再然后给 mSelfObserver 注册 Uri( mNotifyUri )监听。

类: SelfContentServer.java

protectedstaticclassSelfContentObserver extendsContentObserver {
WeakReference<AbstractCursor>mCursor;

publicSelfContentObserver(AbstractCursor cursor) {
super(null);
mCursor= newWeakReference<AbstractCursor>(cursor);
}

@Override
publicbooleandeliverSelfNotifications() {
returnfalse;
}

@Override
publicvoidonChange(booleanselfChange) {
AbstractCursorcursor = mCursor.get();
if(cursor != null){
cursor.onChange(false);
}
}
}

总结一下:在 query 发起者得到了一个 Cursor 对象,并且这个 Cursor 对象的实现类 AbstractCursor 内部会实例化一个 mSelfObserver 对象注册 Uri 的监听。根据观察者模式逻辑,当 uri 执行 notify 方法时,我们的 mSelfObserver 会收到通知并且执行 onChange 方法。

2 、通知 Cursor 中 mSelfObserver , Uri 数据发生改变。

在我们的 ContentProvider 中的 update 以及 insert 或者 delete 方法中,我们在方法执行的最后按照我们的需求,我们会执行如下方法调用(以 update 方法为例):

publicintupdate(Uriuri,ContentValuesvalues,String selection,String[] selectionArgs){
SQLiteDatabasedb = mOpenHelper.getWritableDatabase();
intaffectedRows = 0;
switch(URI_MATCHER.match(uri)){
caseXXX:
break;
caseXXX:
break;
...
default:
break;
}
if(affectedRows> 0){
getContext().getContentResolver().notifyChange(XXX.CONTENT_URI,null);
}
returnaffectedRows;
}

当我们执行方 getContext ().getContentResolver().notifyChange( XXX.CONTENT_URI, null ) ,那么 AbstractCursor 类中的 mSelfObserver 就会收到通知并且回调 onChange 方法。至于在 onChange 方法中做了那些工作,我们稍后介绍,我们先来看一下 cursor 和 cursorAdapter 之间的关系。

3 、 Cursor 和 CursorAdapter 之间的关系。

当我们构建 CursorAdapter 时,我们会将 cursor 对象作为 CursorAdapter 的构造参数传递到 CursorAdapter 中。

类: CursorAdapter.java

publicCursorAdapter(Context context, Cursor c, intflags) {
init(context,c, flags);
}

voidinit(Context context, Cursor c, intflags) {
if((flags & FLAG_AUTO_REQUERY)== FLAG_AUTO_REQUERY){
flags |=FLAG_REGISTER_CONTENT_OBSERVER;
mAutoRequery= true;
} else{
mAutoRequery= false;
}
booleancursorPresent = c != null;
mCursor= c;
mDataValid= cursorPresent;
mContext= context;
mRowIDColumn= cursorPresent ? c.getColumnIndexOrThrow("_id"): -1;
if((flags & FLAG_REGISTER_CONTENT_OBSERVER)== FLAG_REGISTER_CONTENT_OBSERVER){
mChangeObserver= new ChangeObserver();
mDataSetObserver= new MyDataSetObserver();
} else{
mChangeObserver= null;
mDataSetObserver= null;
}

if(cursorPresent) {
if(mChangeObserver != null)
c.registerContentObserver(mChangeObserver);
if(mDataSetObserver != null)
c.registerDataSetObserver(mDataSetObserver);
}
}

总结: CursorAdapter 通过 new 关键字初始化了 mChangeObserver ,mDataSetObserver 两个对象。并且调用 c.registerContentObserver(mChangeObserver ) , c.registerDataSetObserver( mDataSetObserver ) ,这两个方法在 Cursor 中:

类 Cursor.java

publicvoidregisterContentObserver(ContentObserver observer) {
mContentObservable.registerObserver(observer);
}
publicvoidregisterDataSetObserver(DataSetObserver observer) {
mDataSetObservable.registerObserver(observer);
}
mContentObservable 是 ContentObservable 的实例化对象。在这个类中:

类: ContentObservable.java

publicclassContentObservable extendsObservable<ContentObserver> {

@Override
publicvoid registerObserver(ContentObserver observer) {
super.registerObserver(observer);
}

publicvoiddispatchChange(booleanselfChange) {
synchronized(mObservers){
for(ContentObserver observer : mObservers){
if(!selfChange || observer.deliverSelfNotifications()) {
observer.dispatchChange(selfChange);
}
}
}
}

publicvoid notifyChange(boolean selfChange) {
synchronized(mObservers){
for(ContentObserver observer : mObservers) {
observer.onChange(selfChange);
}
}
}
}

我们看到 ContentObservable 继承自 Observable ,典型的观察者模式,这个类是主题类。 registerObserver 方法会将 ContentObserver 加入到列表中,当收到通知会执行 notifyChange 方法,在这个方法内,所有的 ContentObserver 会执行onChange 方法。

mDataSetObservable 是 DataSetObservable 的实例化对象,在这个类中: 类:DataSetObservable.java

publicclassDataSetObservable extendsObservable<DataSetObserver> {

publicvoidnotifyChanged() {
synchronized(mObservers){
for(inti = mObservers.size()- 1; i >= 0; i--) {
mObservers.get(i).onChanged();
}
}
}

publicvoidnotifyInvalidated() {
synchronized(mObservers){
for(inti = mObservers.size()- 1; i >= 0; i--) {
mObservers.get(i).onInvalidated();
}
}
}
}

同样也是继承自 Observer ,同样也是作为观察者中的主题,可以通知注册对象发生变化,执行对象的 onChanged 方法。

总结:关于 CursorAdapter 与 Cursor 的关系,我们可以概括一下, Cursor 中有一套观察者模式,其中维护了两个主题, mContentObservable ,mDataSetObservable 。在这套观察者模式中 CursorAdapter 提供了两个观察者mChangeObserver , mDataSetObserver 。当 Cursor 中的主题通知改变的时候,执行 CursorAdapter 中的两个观察者中的 onChanged 方法。

4 、 CursorAdapter 和 Cursor 以及 ContentProvider 之间的关系

CursorAdapter 与 Cursor 之间通过观察者之间建立关系。

ContentProvider 与 Cursor 之间通过 Uri 之间建立关系。

5 、当 Cursor 监听的 uri 发生了改变(即 Cursor 中的 mSelfObserver 接到通知),业务逻辑。

protectedstaticclassSelfContentObserver extendsContentObserver {
WeakReference<AbstractCursor>mCursor;

publicSelfContentObserver(AbstractCursor cursor) {
super(null);
mCursor= newWeakReference<AbstractCursor>(cursor);
}

@Override
publicbooleandeliverSelfNotifications() {
returnfalse;
}

@Override
publicvoid onChange(boolean selfChange) {
AbstractCursorcursor = mCursor.get();
if(cursor != null) {
cursor.onChange(false);
}
}
}

会执行 cursor.onChange(false);

我们看一下在 onChange 中的业务逻辑:

类: AbstractCursor.java

protectedvoidonChange(booleanselfChange) {
synchronized(mSelfObserverLock){
mContentObservable.dispatchChange(selfChange);
if(mNotifyUri != null && selfChange) {
mContentResolver.notifyChange(mNotifyUri,mSelfObserver);
}
}
}

执行 mContentObservable.dispatchChange(false) 方法,通过 3 中可知,执行逻辑如下:

类 ContentObservable.java

publicvoiddispatchChange(booleanselfChange) {
synchronized(mObservers){
for(ContentObserver observer : mObservers){
if(!selfChange || observer.deliverSelfNotifications()) {
observer.dispatchChange(selfChange);
}
}
}

会执行所有注册的观察者的 dispatchChange(false) 方法 ;

在 dispatchChange ( false )中的业务逻辑:

6, 在 5 、中触发的观察者在 dispatchChange ( false )方法时的业务逻辑

首先会执行 ChangeObserver 的父类 ContentObserver 的 dispatchChange (false )方法:

类: ContentObserver.java

publicfinalvoiddispatchChange(booleanselfChange) {
if(mHandler== null){
onChange(selfChange);
} else{
mHandler.post(newNotificationRunnable(selfChange));
}
}

我们看到会执行 onChange ( false );

类 CursorAdapter$ChangeObserver.java

privateclassChangeObserver extendsContentObserver {
publicChangeObserver() {
super(newHandler());
}

@Override
publicbooleandeliverSelfNotifications() {
returntrue;
}

@Override
publicvoidonChange(booleanselfChange) {
onContentChanged();
}
}

然后会执行 onContentChanged() 方法;

protectedvoidonContentChanged() {
if(mAutoRequery&& mCursor!= null&& !mCursor.isClosed()){
mDataValid= mCursor.requery();
}
}

在这里我们找到了我们的答案, mCursor.requery(), 会重新刷新并填充 mCursor对象。

然后还没有结束:

我们的 cursor 重新填充了,但是不会告诉 Adapter 执行 notifyDataSetChanged()方法,因为只有执行了这个方法,我们的界面才会刷新。

7 、通知 Adapter 执行 notifyDataSetChanged() 方法。

当我们的 Cursor 执行 requery 方法的时候,我们看一下业务逻辑:

类: AbstractCursor.java

publicbooleanrequery() {
if(mSelfObserver!= null&& mSelfObserverRegistered== false){
mContentResolver.registerContentObserver(mNotifyUri,true,mSelfObserver);
mSelfObserverRegistered= true;
}
mDataSetObservable.notifyChanged();
returntrue;
}

我们看到我们最后一位主角登场了,他就是 mDataSetObservable ,通过 3 、可知,这是个主题,当它 notifyChanged 的时候,它的所有的观察者会执行 onChanged方法。

我们看一下观察者的业务逻辑:

类: CursorAdapter$MyDataSetObserver.java

privateclassMyDataSetObserver extendsDataSetObserver {
@Override
publicvoidonChanged() {
mDataValid= true;
notifyDataSetChanged();
}

@Override
publicvoidonInvalidated() {
mDataValid= false;
notifyDataSetInvalidated();
}
}

在 onChanged 方法中,我们看到了我们的答案, notifySetChanged ();

总结:我们在使用 Cursor , CursorAdapter 搭配 ListView 进行上层业务开发的过程中,我们只要合理的利用 android 提供的框架。我们可以在数据插入数据库之后,自动进行页面的刷新。

附:

 
原文地址:https://www.cnblogs.com/xiaoxiaoshen/p/5199922.html