-
概述
Android应用程序组件Content Provider中的数据更新通知机制和Android系统中的广播通知机制的有点类似。它们有三个主要区别,区别一是前者是通过URI来把通知的发送者和接收者关联在一起的,而后者是通过intent来关联的;二是前者的通知注册中心是由ContentService服务来扮演,而后者是由ActivityManagerService服务来扮演的;三是前者负责接收数据更新通知的类必须要继承ContentObserver类,而后者要继承BroadcastReceiver类。下面分三个部分来分析数据更新流程。1、ContentService的启动过程;2、监控数据变化的ContentObserver的注册过程;3、数据更新通知的发送过程。
-
ContentService的启动过程
Android系统进程Zygote在启动的时候,会加载系统的一些关键服务,ContentService就这些关键服务之一。如图所示:
private static final String CONTENT_SERVICE_CLASS = "com.android.server.content.ContentService$Lifecycle";
mSystemServiceManager.startService(CONTENT_SERVICE_CLASS);
public final class ContentService extends IContentService.Stub { static final String TAG = "ContentService"; static final boolean DEBUG = false; public static class Lifecycle extends SystemService { private ContentService mService; public Lifecycle(Context context) { super(context); } @Override public void onStart() { final boolean factoryTest = (FactoryTest .getMode() == FactoryTest.FACTORY_TEST_LOW_LEVEL); mService = new ContentService(getContext(), factoryTest); publishBinderService(ContentResolver.CONTENT_SERVICE_NAME, mService); }
protected final void publishBinderService(String name, IBinder service) { publishBinderService(name, service, false); } /** * Publish the service so it is accessible to other services and apps. */ protected final void publishBinderService(String name, IBinder service, boolean allowIsolated) { ServiceManager.addService(name, service, allowIsolated); }
可以看出,在ContentService的内部类Lifecycle类的onStart函数中,会创建ContentService实例,然后把它添加到ServiceManager中去,这样ContentService服务就启动起来了,其他地方就可以通过ServiceManager来获得它的一个远程接口来使用它提供的服务。
-
ContentOberver的注册过程
在应用层注册观察者需要继承ContentObserver并实现onChange函数。当这个ContentObserver子类负责监控的数据发生变化时,ContentService就会调用它的onChange函数来处理。注册过程如下:
public void registerContentObserver(Uri uri, boolean notifyForDescendants, IContentObserver observer, int userHandle) { synchronized (mRootNode) { mRootNode.addObserverLocked(uri, observer, notifyForDescendants, mRootNode, uid, pid, userHandle); if (false) Log.v(TAG, "Registered observer " + observer + " at " + uri + " with notifyForDescendants " + notifyForDescendants); }
最后调用了ContentService类的成员变量mRootNode的addObserverLocked函数来注册这个ContentObserver对象observer,成员变量mRootNode的类型为ContentService在内部定义的一个类ObserverNode。注册到ContentService中的ContentObserver按照树形来组织,树的节点类型为ObserverNode,而树的根节点就为ContentService类的成员变量mRootNode,每一个ObserverNode节点都对应一个名字,它是从URI中解析出来的。
-
数据更新通知的发送过程
在联系人数据库的增删改查操作都会发出通知,如下:
public Uri insert(Uri uri, ContentValues values) { ContactsTransaction transaction = startTransaction(false); try { Uri result = insertInTransaction(uri, values); if (result != null) { transaction.markDirty(); } transaction.markSuccessful(false); return result; } finally { endTransaction(false); } }
private void endTransaction(boolean callerIsBatch) { ContactsTransaction transaction = mTransactionHolder.get(); if (transaction != null && (!transaction.isBatch() || callerIsBatch)) { try { if (transaction.isDirty()) { notifyChange(); } } } }
protected void notifyChange() { notifyChange(mSyncToNetwork); mSyncToNetwork = false; } protected void notifyChange(boolean syncToNetwork) { getContext().getContentResolver().notifyChange(ContactsContract.AUTHORITY_URI, null, syncToNetwork); }
从上面可看出在content provider中会调用notifyChange来通知那些注册了监控content://com.android.contacts这个URI的ContentObserver,它监控的数据发生变化了。
最后还是调用到了ContentService中:
public void notifyChange(Uri uri, IContentObserver observer, boolean observerWantsSelfNotifications, int flags, int userHandle) { try { ArrayList<ObserverCall> calls = new ArrayList<ObserverCall>(); synchronized (mRootNode) { mRootNode.collectObserversLocked(uri, 0, observer, observerWantsSelfNotifications, flags, userHandle, calls); } final int numCalls = calls.size(); for (int i=0; i<numCalls; i++) { ObserverCall oc = calls.get(i); try { oc.mObserver.onChange(oc.mSelfChange, uri, userHandle); if (DEBUG) Slog.d(TAG, "Notified " + oc.mObserver + " of " + "update at " + uri); } } }
这里会先调用collectObserverLocked函数来手机那些注册了上面URI的ContentObserver,然后分别调用这些ContentObserver的onChange函数来通知它们监控的数据发生变化了。
android数据库更新简介