8.2 数据更新通知机制分析

何为数据更新通知?先来看日常生活中的一个例子。

笔者所在公司采用BugZilla来管理Bug。在日常工作中,笔者和同事们的一部分工作就是登录BugZilla查询各自名下的Bug并修改它们。如何跟踪自己的Bug呢?其实,以上描述中已经提到了一种方法,即登录BugZilla并查询。除此之外,BugZilla还支持另一种方法,即为每个Bug设置一个关系人列表,一旦该Bug的状态发生变化,BugZilla就会给该Bug关系人列表中的人发送邮件。

上例中提到的第二种方法就是本节要分析的数据更新通知机制。一般说来,领导和项目经理(PM)使用第一种方法的居多,因为他们需要不定时地查询和统计全局Bug的情况。而程序员使用第二种方法较多(也许是没办法的事情吧,谁会情愿主动查询自己的Bug呢?)。

类似的通知机制在日常生活中的其他地方还有使用。在操作系统中,这种通知机制同样也广泛存在。例如,在OS中,设计人员一般会安排外部设备以中断的方式通知CPU并让其开展后续处理,而不会让CPU去轮询外设的状态。

现在回到Android平台,如果程序需要监控某数据项的变化,可以采用一个类似while循环的语句不断查询它以判断其值是否发生了变化。显而易见,这种方式的效率很低。有了通知机制以后,程序只需注册一个ContentObserver实例即可。一旦该项数据发生变化,系统就会通过ContentObserver的onChange函数来通知我们。与前面所述的轮询相比,此处的通知方式明显更高效。

通过上面的描述可以知道,通知机制的实施包括两个步骤:第一步,注册观察者;第二步,通知观察者。在Android平台中,这两步都离不开ContentService,下面来认识一下它。

提示 在设计模式中,通知机制对应的模式是Observer模式,即观察者模式。

8.2.1 初识ContentService

SystemServer创建ContentService的代码非常简单,如下所示:

[—>SystemServer. java:ServerThread.run]


public void run(){

……

ContentService.main(context,

factoryTest==SystemServer.FACTORY_TEST_LOW_LEVEL);

……

}


以上代码中直接调用了ContentService的main函数。在一般情况下,该函数第二个参数为false。此main函数的代码如下:

[—>ContentService. java:main]


public static IContentService main(Context context, boolean factoryTest){

//构造ContentService实例

ContentService service=new ContentService(context, factoryTest);

//将ContentService注册到ServiceManager中,其注册名叫content

ServiceManager.addService(ContentResolver.CONTENT_SERVICE_NAME,

service);

return service;

}


ContentService的构造函数的代码如下:

[—>ContentService. java:ContentService]


ContentService(Context context, boolean factoryTest){

mContext=context;

mFactoryTest=factoryTest;

getSyncManager();//获取同步服务管理对象,接下来看它的代码

}


[—>ContentService. java:getSyncManager]


private SyncManager getSyncManager(){

synchronized(mSyncManagerLock){

try{

//创建一个SyncManager实例,它是ContentService中负责数据同步服务的

//主力成员。留待8.4节再详细分析它

if(mSyncManager==null)mSyncManager=new

SyncManager(mContext, mFactoryTest);

}……

return mSyncManager;

}

}


看完以上代码读者可能会觉得ContentService比较简单。其实,ContentService中最难实现的功能是数据同步服务,不过该功能的实现都封装在SyncManager及相关类中了,所以在分析通知机制时不会和数据同步服务有太多瓜葛。

下面来分析通知机制实施的第一步,即注册ContentObserver。该步骤由ContentResovler提供的registerContentObserver函数来实现。