概述
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函数来通知它们监控的数据发生变化了。
本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。