Cursor和CursorAdapter中的观察者模式机制

来源:互联网 发布:golang syscall包 编辑:程序博客网 时间:2024/04/30 16:08

转载请注明出处:http://blog.csdn.net/droyon/article/details/9360099

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


1ContentProviderCursor之间的关系。

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

[java] view plaincopy
  1. public Cursor query(Uri uri,String[] projection,String selection,String[] selectionArgs,String sortOrder){  
  2.           
  3.         SQLiteDatabase db = mOpenHelper.getReadableDatabase();  
  4.           
  5.         Cursor cursor = null;  
  6.         switch(URI_MATCHER.match(uri)){  
  7.         case XXX:  
  8.             break;  
  9.         case XXX:  
  10.             break;  
  11.             ..  
  12.             default:  
  13.                 break;  
  14.         }  
  15.         if(cursor != null){  
  16.             cursor.setNotificationUri(getContext().getContentResolver(), XXX.CONTENT_URI);  
  17.         }  
  18.         return cursor;  
  19.     }  

setNotificationUri方法中执行内容如下:

类:AbstractCursor.java

[java] view plaincopy
  1. public void setNotificationUri(ContentResolver cr, Uri notifyUri) {  
  2.         synchronized (mSelfObserverLock) {  
  3.             mNotifyUri = notifyUri;  
  4.             mContentResolver = cr;  
  5.             if (mSelfObserver != null) {  
  6.                 mContentResolver.unregisterContentObserver(mSelfObserver);  
  7.             }  
  8.             mSelfObserver = new SelfContentObserver(this);  
  9.             mContentResolver.registerContentObserver(mNotifyUri, true, mSelfObserver);  
  10.             mSelfObserverRegistered = true;  
  11.         }  
  12.     }  

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

类:SelfContentServer.java

[java] view plaincopy
  1. protected static class SelfContentObserver extends ContentObserver {  
  2.         WeakReference<AbstractCursor> mCursor;  
  3.   
  4.         public SelfContentObserver(AbstractCursor cursor) {  
  5.             super(null);  
  6.             mCursor = new WeakReference<AbstractCursor>(cursor);  
  7.         }  
  8.   
  9.         @Override  
  10.         public boolean deliverSelfNotifications() {  
  11.             return false;  
  12.         }  
  13.   
  14.         @Override  
  15.         public void onChange(boolean selfChange) {  
  16.             AbstractCursor cursor = mCursor.get();  
  17.             if (cursor != null) {  
  18.                 cursor.onChange(false);  
  19.             }  
  20.         }  
  21.     }  

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

2、通知CursormSelfObserverUri数据发生改变。

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

[java] view plaincopy
  1. public int update(Uri uri,ContentValues values,String selection,String[] selectionArgs){  
  2.         SQLiteDatabase db = mOpenHelper.getWritableDatabase();  
  3.         int affectedRows = 0;  
  4.         switch(URI_MATCHER.match(uri)){  
  5.         case XXX:  
  6.             break;  
  7.         case XXX:  
  8.             break;  
  9.             ...  
  10.             default:  
  11.                 break;  
  12.         }  
  13.           
  14.         if(affectedRows > 0){  
  15.             getContext().getContentResolver().notifyChange(XXX.CONTENT_URI,null);  
  16.         }  
  17.         return affectedRows;  
  18.     }  

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

3CursorCursorAdapter之间的关系。

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

类:CursorAdapter.java

[java] view plaincopy
  1. public CursorAdapter(Context context, Cursor c, int flags) {  
  2.         init(context, c, flags);  
  3. }  
  4.   
  5. void init(Context context, Cursor c, int flags) {  
  6.         if ((flags & FLAG_AUTO_REQUERY) == FLAG_AUTO_REQUERY) {  
  7.             flags |= FLAG_REGISTER_CONTENT_OBSERVER;  
  8.             mAutoRequery = true;  
  9.         } else {  
  10.             mAutoRequery = false;  
  11.         }  
  12.         boolean cursorPresent = c != null;  
  13.         mCursor = c;  
  14.         mDataValid = cursorPresent;  
  15.         mContext = context;  
  16.         mRowIDColumn = cursorPresent ? c.getColumnIndexOrThrow("_id") : -1;  
  17.         if ((flags & FLAG_REGISTER_CONTENT_OBSERVER) == FLAG_REGISTER_CONTENT_OBSERVER) {  
  18.             mChangeObserver = new ChangeObserver();  
  19.             mDataSetObserver = new MyDataSetObserver();  
  20.         } else {  
  21.             mChangeObserver = null;  
  22.             mDataSetObserver = null;  
  23.         }  
  24.   
  25.         if (cursorPresent) {  
  26.             if (mChangeObserver != null)          
  27.                     c.registerContentObserver(mChangeObserver);  
  28.             if (mDataSetObserver != null)   
  29.                     c.registerDataSetObserver(mDataSetObserver);  
  30.         }  
  31.     }  

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

Cursor.java

[java] view plaincopy
  1. public void registerContentObserver(ContentObserver observer) {  
  2.         mContentObservable.registerObserver(observer);  
  3. }  
  4. public void registerDataSetObserver(DataSetObserver observer) {  
  5.         mDataSetObservable.registerObserver(observer);  
  6. }  

mContentObservableContentObservable的实例化对象。在这个类中:

类:ContentObservable.java

[java] view plaincopy
  1. public class ContentObservable extends Observable<ContentObserver> {  
  2.   
  3.     @Override  
  4.     public void registerObserver(ContentObserver observer) {  
  5.         super.registerObserver(observer);  
  6.     }  
  7.   
  8.     public void dispatchChange(boolean selfChange) {  
  9.         synchronized(mObservers) {  
  10.             for (ContentObserver observer : mObservers) {  
  11.                 if (!selfChange || observer.deliverSelfNotifications()) {  
  12.                     observer.dispatchChange(selfChange);  
  13.                 }  
  14.             }  
  15.         }  
  16.     }  
  17.   
  18.     public void notifyChange(boolean selfChange) {  
  19.         synchronized(mObservers) {  
  20.             for (ContentObserver observer : mObservers) {  
  21.                 observer.onChange(selfChange);  
  22.             }  
  23.         }  
  24.     }  
  25. }  

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

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

[java] view plaincopy
  1. public class DataSetObservable extends Observable<DataSetObserver> {  
  2.   
  3.     public void notifyChanged() {  
  4.         synchronized(mObservers) {  
  5.             for (int i = mObservers.size() - 1; i >= 0; i--) {  
  6.                 mObservers.get(i).onChanged();  
  7.             }  
  8.         }  
  9.     }  
  10.   
  11.     public void notifyInvalidated() {  
  12.         synchronized (mObservers) {  
  13.             for (int i = mObservers.size() - 1; i >= 0; i--) {  
  14.                 mObservers.get(i).onInvalidated();  
  15.             }  
  16.         }  
  17.     }  
  18. }  

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

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

4CursorAdapterCursor以及ContentProvider之间的关系

CursorAdapterCursor之间通过观察者之间建立关系。

ContentProviderCursor之间通过Uri之间建立关系。


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

[java] view plaincopy
  1. protected static class SelfContentObserver extends ContentObserver {  
  2.         WeakReference<AbstractCursor> mCursor;  
  3.   
  4.         public SelfContentObserver(AbstractCursor cursor) {  
  5.             super(null);  
  6.             mCursor = new WeakReference<AbstractCursor>(cursor);  
  7.         }  
  8.   
  9.         @Override  
  10.         public boolean deliverSelfNotifications() {  
  11.             return false;  
  12.         }  
  13.   
  14.         @Override  
  15.         public void onChange(boolean selfChange) {  
  16.             AbstractCursor cursor = mCursor.get();  
  17.             if (cursor != null) {  
  18.                 cursor.onChange(false);  
  19.             }  
  20.         }  
  21.     }  

会执行cursor.onChange(false);

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

类:AbstractCursor.java

[java] view plaincopy
  1. protected void onChange(boolean selfChange) {  
  2.         synchronized (mSelfObserverLock) {  
  3.             mContentObservable.dispatchChange(selfChange);  
  4.             if (mNotifyUri != null && selfChange) {  
  5.                 mContentResolver.notifyChange(mNotifyUri, mSelfObserver);  
  6.             }  
  7.         }  
  8. }  

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

ContentObservable.java

[java] view plaincopy
  1. public void dispatchChange(boolean selfChange) {  
  2.         synchronized(mObservers) {  
  3.             for (ContentObserver observer : mObservers) {  
  4.                 if (!selfChange || observer.deliverSelfNotifications()) {  
  5.                     observer.dispatchChange(selfChange);  
  6.                 }  
  7.             }  
  8.  }  

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

dispatchChangefalse)中的业务逻辑:


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

首先会执行ChangeObserver的父类ContentObserverdispatchChangefalse)方法:

类:ContentObserver.java

[java] view plaincopy
  1. public final void dispatchChange(boolean selfChange) {  
  2.         if (mHandler == null) {  
  3.             onChange(selfChange);  
  4.         } else {  
  5.             mHandler.post(new NotificationRunnable(selfChange));  
  6.         }  
  7. }  

我们看到会执行onChangefalse);

CursorAdapter$ChangeObserver.java

[java] view plaincopy
  1. private class ChangeObserver extends ContentObserver {  
  2.         public ChangeObserver() {  
  3.             super(new Handler());  
  4.         }  
  5.   
  6.         @Override  
  7.         public boolean deliverSelfNotifications() {  
  8.             return true;  
  9.         }  
  10.   
  11.         @Override  
  12.         public void onChange(boolean selfChange) {  
  13.             onContentChanged();  
  14.         }  
  15. }  

然后会执行onContentChanged()方法;

[java] view plaincopy
  1. protected void onContentChanged() {  
  2.         if (mAutoRequery && mCursor != null && !mCursor.isClosed()) {  
  3.             mDataValid = mCursor.requery();  
  4.         }  
  5. }  
在这里我们找到了我们的答案,mCursor.requery(),会重新刷新并填充mCursor对象。

然后还没有结束:

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

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

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

类:AbstractCursor.java

[java] view plaincopy
  1. public boolean requery() {  
  2.         if (mSelfObserver != null && mSelfObserverRegistered == false) {  
  3.             mContentResolver.registerContentObserver(mNotifyUri, true, mSelfObserver);  
  4.             mSelfObserverRegistered = true;  
  5.         }  
  6.         mDataSetObservable.notifyChanged();  
  7.         return true;  
  8. }  

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


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

类:CursorAdapter$MyDataSetObserver.java

[java] view plaincopy
  1. private class MyDataSetObserver extends DataSetObserver {  
  2.         @Override  
  3.         public void onChanged() {  
  4.             mDataValid = true;  
  5.             notifyDataSetChanged();  
  6.         }  
  7.   
  8.         @Override  
  9.         public void onInvalidated() {  
  10.             mDataValid = false;  
  11.             notifyDataSetInvalidated();  
  12.         }  
  13. }  
onChanged方法中,我们看到了我们的答案,notifySetChanged();


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



0 0
原创粉丝点击