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

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

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


1ContentProviderCursor之间的关系。

我们使用UriContentProvider发起一个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,解除mSelfObserveruri的监听。然后重新使用new进行实例化一个mSelfObserver对象,mSelfObserver继承自ContentObserver。再然后给mSelfObserver注册UrimNotifyUri)监听。

类: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、通知CursormSelfObserverUri数据发生改变。

在我们的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方法中做了那些工作,我们稍后介绍,我们先来看一下cursorcursorAdapter之间的关系。

3CursorCursorAdapter之间的关系。

当我们构建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关键字初始化了mChangeObservermDataSetObserver两个对象。并且调用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方法。

mDataSetObservableDataSetObservable的实例化对象,在这个类中:
类: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方法。

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

4CursorAdapterCursor以及ContentProvider之间的关系

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

ContentProviderCursor之间通过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)方法;

dispatchChangefalse)中的业务逻辑:


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

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

类:ContentObserver.java

public final void dispatchChange(boolean selfChange) {
        if (mHandler == null) {
            onChange(selfChange);
        } else {
            mHandler.post(new NotificationRunnable(selfChange));
        }
}

我们看到会执行onChangefalse);

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 ();


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

附:




关注我的技术公众号,查看更多优质技术文章推送

微信扫一扫下方二维码即可关注:

关注我的技术公众号,查看更多优质技术文章推送


  • 5
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 8
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

hailushijie

您的鼓励是我创作最大的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值