转载请注明出处:http://blog.csdn.net/droyon/article/details/9360099
Cursor,CursorAdapter配合ListView一起使用,当数据发生改变的时候,可以实现列表数据自动刷新。现在介绍一下内中原理。
1、ContentProvider与Cursor之间的关系。
我们使用Uri向ContentProvider发起一个query请求用来得到Cursor对象。但在cursor对象返回之前,我们会给cursor对象执行setNotificationUri()方法。
public Cursor query(Uri uri,String[] projection,String selection,String[] selectionArgs,String sortOrder){ SQLiteDatabase db = mOpenHelper.getReadableDatabase(); Cursor cursor = null; switch(URI_MATCHER.match(uri)){ case XXX: break; case XXX: break; .. default: break; } if(cursor != null){ cursor.setNotificationUri(getContext().getContentResolver(), XXX.CONTENT_URI); } return cursor; }
在setNotificationUri方法中执行内容如下:
类:AbstractCursor.java
public void setNotificationUri(ContentResolver cr, Uri notifyUri) { synchronized (mSelfObserverLock) { mNotifyUri = notifyUri; mContentResolver = cr; if (mSelfObserver != null) { mContentResolver.unregisterContentObserver(mSelfObserver); } mSelfObserver = new SelfContentObserver(this); mContentResolver.registerContentObserver(mNotifyUri, true, mSelfObserver); mSelfObserverRegistered = true; } }
在这个方法内部,首先检查mSelfObserver是否为null,如果不为null,解除mSelfObserver对uri的监听。然后重新使用new进行实例化一个mSelfObserver对象,mSelfObserver继承自ContentObserver。再然后给mSelfObserver注册Uri(mNotifyUri)监听。
类:SelfContentServer.java
protected static class SelfContentObserver extends ContentObserver { WeakReference<AbstractCursor> mCursor; public SelfContentObserver(AbstractCursor cursor) { super(null); mCursor = new WeakReference<AbstractCursor>(cursor); } @Override public boolean deliverSelfNotifications() { return false; } @Override public void onChange(boolean selfChange) { AbstractCursor cursor = 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方法为例):
public int update(Uri uri,ContentValues values,String selection,String[] selectionArgs){ SQLiteDatabase db = mOpenHelper.getWritableDatabase(); int affectedRows = 0; switch(URI_MATCHER.match(uri)){ case XXX: break; case XXX: break; ... default: break; } if(affectedRows > 0){ getContext().getContentResolver().notifyChange(XXX.CONTENT_URI,null); } return affectedRows; }
当我们执行方getContext().getContentResolver().notifyChange(XXX.CONTENT_URI,null),那么AbstractCursor类中的mSelfObserver就会收到通知并且回调onChange方法。至于在onChange方法中做了那些工作,我们稍后介绍,我们先来看一下cursor和cursorAdapter之间的关系。
3、Cursor和CursorAdapter之间的关系。
当我们构建CursorAdapter时,我们会将cursor对象作为CursorAdapter的构造参数传递到CursorAdapter中。
类:CursorAdapter.java
public CursorAdapter(Context context, Cursor c, int flags) { init(context, c, flags); } void init(Context context, Cursor c, int flags) { if ((flags & FLAG_AUTO_REQUERY) == FLAG_AUTO_REQUERY) { flags |= FLAG_REGISTER_CONTENT_OBSERVER; mAutoRequery = true; } else { mAutoRequery = false; } boolean cursorPresent = 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
public void registerContentObserver(ContentObserver observer) { mContentObservable.registerObserver(observer); } public void registerDataSetObserver(DataSetObserver observer) { mDataSetObservable.registerObserver(observer); }mContentObservable 是 ContentObservable 的实例化对象。在这个类中:
类:ContentObservable.java
public class ContentObservable extends Observable<ContentObserver> { @Override public void registerObserver(ContentObserver observer) { super.registerObserver(observer); } public void dispatchChange(boolean selfChange) { synchronized(mObservers) { for (ContentObserver observer : mObservers) { if (!selfChange || observer.deliverSelfNotifications()) { observer.dispatchChange(selfChange); } } } } public void notifyChange(boolean selfChange) { synchronized(mObservers) { for (ContentObserver observer : mObservers) { observer.onChange(selfChange); } } } }
我们看到ContentObservable继承自Observable,典型的观察者模式,这个类是主题类。registerObserver方法会将ContentObserver加入到列表中,当收到通知会执行notifyChange方法,在这个方法内,所有的ContentObserver会执行onChange方法。
mDataSetObservable是DataSetObservable的实例化对象,在这个类中:
类:DataSetObservable.java
public class DataSetObservable extends Observable<DataSetObserver> { public void notifyChanged() { synchronized(mObservers) { for (int i = mObservers.size() - 1; i >= 0; i--) { mObservers.get(i).onChanged(); } } } public void notifyInvalidated() { synchronized (mObservers) { for (int i = 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接到通知),业务逻辑。
protected static class SelfContentObserver extends ContentObserver { WeakReference<AbstractCursor> mCursor; public SelfContentObserver(AbstractCursor cursor) { super(null); mCursor = new WeakReference<AbstractCursor>(cursor); } @Override public boolean deliverSelfNotifications() { return false; } @Override public void onChange(boolean selfChange) { AbstractCursor cursor = mCursor.get(); if (cursor != null) { cursor.onChange(false); } } }
会执行cursor.onChange(false);
我们看一下在onChange中的业务逻辑:
类:AbstractCursor.java
protected void onChange(boolean selfChange) { synchronized (mSelfObserverLock) { mContentObservable.dispatchChange(selfChange); if (mNotifyUri != null && selfChange) { mContentResolver.notifyChange(mNotifyUri, mSelfObserver); } } }
执行mContentObservable.dispatchChange(false)方法,通过3中可知,执行逻辑如下:
类ContentObservable.java
public void dispatchChange(boolean selfChange) { 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
public final void dispatchChange(boolean selfChange) { if (mHandler == null) { onChange(selfChange); } else { mHandler.post(new NotificationRunnable(selfChange)); } }
我们看到会执行onChange(false);
类CursorAdapter$ChangeObserver.java
private class ChangeObserver extends ContentObserver { public ChangeObserver() { super(new Handler()); } @Override public boolean deliverSelfNotifications() { return true; } @Override public void onChange(boolean selfChange) { onContentChanged(); } }
然后会执行onContentChanged()方法;
protected void onContentChanged() { if (mAutoRequery && mCursor != null && !mCursor.isClosed()) { mDataValid = mCursor.requery(); } }在这里我们找到了我们的答案, mCursor.requery(), 会重新刷新并填充 mCursor 对象。
然后还没有结束:
我们的cursor重新填充了,但是不会告诉Adapter执行notifyDataSetChanged()方法,因为只有执行了这个方法,我们的界面才会刷新。
7、通知Adapter执行notifyDataSetChanged()方法。
当我们的Cursor执行requery方法的时候,我们看一下业务逻辑:
类:AbstractCursor.java
public boolean requery() { if (mSelfObserver != null && mSelfObserverRegistered == false) { mContentResolver.registerContentObserver(mNotifyUri, true, mSelfObserver); mSelfObserverRegistered = true; } mDataSetObservable.notifyChanged(); return true; }
我们看到我们最后一位主角登场了,他就是mDataSetObservable,通过3、可知,这是个主题,当它notifyChanged的时候,它的所有的观察者会执行onChanged方法。
我们看一下观察者的业务逻辑:
类:CursorAdapter$MyDataSetObserver.java
private class MyDataSetObserver extends DataSetObserver { @Override public void onChanged() { mDataValid = true; notifyDataSetChanged(); } @Override public void onInvalidated() { mDataValid = false; notifyDataSetInvalidated(); } }在 onChanged 方法中,我们看到了我们的答案, notifySetChanged ();
总结:我们在使用Cursor,CursorAdapter搭配ListView进行上层业务开发的过程中,我们只要合理的利用android提供的框架。我们可以在数据插入数据库之后,自动进行页面的刷新。
附: