在Android系统中,应用程序组件Content Provider为不同的应用程序实现数据共享提供了基础设施,它主要通过Binder进程间通信机制和匿名共享内存机制来实现的。关于数据共享的另一个话题便是数据更新通知机制了,即如果一个应用程序对共享数据做了修改,它应该如何通知其它正在使用这些共享数据的应用程序呢?本文将分析Content Provider的共享数据更新通知机制,为读者解答这个问题。
        Android应用程序组件Content Provider中的数据更新通知机制和Android系统中的广播(Broadcast)通知机制的实现思路是相似的。在Android的广播机制中,首先是接收者对自己感兴趣的广播进行注册,接着当发送者发出这些广播时,接收者就会得到通知了。更多关于Android系统的广播机制的知识,可以参考前面 Android系统中的广播(Broadcast)机制简要介绍和学习计划 这一系列文章。然而,Content Provider中的数据监控机制与Android系统中的广播机制又有三个主要的区别,一是前者是通过URI来把通知的发送者和接收者关联在一起的,而后者是通过Intent来关联的,二是前者的通知注册中心是由ContentService服务来扮演的,而后者是由ActivityManagerService服务来扮演的,三是前者负责接收数据更新通知的类必须要继承ContentObserver类,而后者要继承BroadcastReceiver类。之所以会有这些区别,是由于Content Proivder组件的数据共享功能本身就是建立在URI的基础之上的,因此专门针对URI来设计另外一套通知机制会更实用和方便,而Android系统的广播机制是一种更加通用的事件通知机制,它的适用范围会更广泛一些。
        与分析Android系统的广播机制类似,我们把Content Provider的数据更新机制划分为三个单元进行分析,第一个单元是ContentService的启动过程,第二个单元是监控数据变化的ContentObserver的注册过程,第二个单元是数据更新通知的发送过程。
        与前面两篇文章 Android应用程序组件Content Provider的启动过程源代码分析 Android应用程序组件Content Provider在应用程序之间共享数据的原理分析 一样,本文仍然以 Android应用程序组件Content Provider应用实例 这篇文章介绍的应用程序为例来分析Content Provider的数据更新机制。
        1. ContentService的启动过程分析
 
        前面提到,在Content Provider的数据更新通知机制中,ContentService扮演者ContentObserver的注册中心的角色,因此,它必须要系统启动的时候就启动起来,以便后面启动起来的应用程序可以使用它。在前面这篇文章 Android系统进程Zygote启动过程的源代码分析 中,我们提到,Android系统进程Zygote在启动的时候,在启动一个System进程来加载系统的一些关键服务,而ContentService就这些关键服务之一了。在System进程中,负责加载系统关键服务的类为SystemServer类,它定义在frameworks/base/services/java/com/android/server/SystemServer.java文件中,它会通过启动一个线程SystemThread来加载这些关键服务:
 
  
  1. class ServerThread extends Thread {   
  2.     ......   
  3.    
  4.     @Override   
  5.     public void run() {   
  6.         ......   
  7.    
  8.         Looper.prepare();   
  9.    
  10.         // Critical services...   
  11.         try {   
  12.             ......   
  13.    
  14.             ContentService.main(context,   
  15.                 factoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL);   
  16.    
  17.             ......   
  18.    
  19.         }catch (RuntimeException e) {   
  20.             ......   
  21.         }   
  22.    
  23.         ......   
  24.    
  25.         Looper.loop();   
  26.         ......   
  27.     }   
  28. }   
       ContentService类定义在frameworks/base/core/java/android/content/ContentService.java文件中,它的main函数的实现如下所示:
 
  
  1. public final class ContentService extends IContentService.Stub {   
  2.     ......   
  3.    
  4.     public static IContentService main(Context context, boolean factoryTest) {   
  5.         ContentService service = new ContentService(context, factoryTest);   
  6.         ServiceManager.addService(ContentResolver.CONTENT_SERVICE_NAME, service);   
  7.         return service;   
  8.     }   
  9.    
  10.     ......   
  11. }   
        从这里我们就可以看到,在ContentService类的main函数中,会创建一个ContentService实例,然后把它添加到ServiceManager中去,这样,ContentService服务就启动起来了,  其它地方可以通过ServiceManager来获得它的一个远程接口来使用它提供的服务。

        2. ContentObserver的注册过程分析
        在前面这篇文章 Android应用程序组件Content Provider应用实例 介绍的应用程序Acticle中,主窗口MainActivity在创建的时候,会调用应用程序上下文的ContentResolver接口来注册一个自定义的ContentObserver来监控ArticlesProvider这个Content Provider中的数据变化:
 
  
  1. public class MainActivity extends Activity implements View.OnClickListener, AdapterView.OnItemClickListener {   
  2.     ......   
  3.    
  4.     private ArticleAdapter adapter = null;   
  5.     private ArticleObserver observer = null;   
  6.    
  7.     ......   
  8.    
  9.     @Override   
  10.     public void onCreate(Bundle savedInstanceState) {   
  11.         super.onCreate(savedInstanceState);   
  12.         ......   
  13.    
  14.         observer = new ArticleObserver(new Handler());   
  15.         getContentResolver().registerContentObserver(Articles.CONTENT_URI, true, observer);   
  16.    
  17.         ......   
  18.     }   
  19.    
  20.     private class ArticleObserver extends ContentObserver {   
  21.         public ArticleObserver(Handler handler) {   
  22.             super(handler);   
  23.         }   
  24.    
  25.         @Override   
  26.         public void onChange (boolean selfChange) {   
  27.             adapter.notifyDataSetChanged();   
  28.         }   
  29.     }   
  30.    
  31.     ......   
  32. }   
        从ContentObserver继承下来的子类必须要实现onChange函数。当这个ContentObserver子类负责监控的数据发生变化时,ContentService就会调用它的onChange函数来处理,参数selfChange表示这个变化是否是由自己引起的,在我们这个情景中,不需要关注这个参数的值。在这个应用程序中,ArticleObserver继承了ContentObserver类,它负责监控的URI是Articles.CONTENT_URI,它的值为"content://shy.luo.providers.articles/item",这个值是在这篇文章 Android应用程序组件Content Provider应用实例 介绍的应用程序ActiclesProvider中的Articles.java文件中定义的。当所有以Articles.CONTENT_URI为前缀的URI对应的数据发生改变时,ContentService都会调用这个ArticleObserver类的onChange函数来处理。在ArticleObserver类的onChange函数中,执行的操作就是重新获取ActiclesProvider中的数据来更新界面上的文章信息列表。

 
        在ArticleObserver类的构造函数中,有一个参数handler,它的类型为Handler,它是从MainActivity类的onCreate函数中创建并传过来的。通过前面这篇文章 Android应用程序消息处理机制(Looper、Handler)分析 的学习,我们知道,这个handler是用来分发和处理消息用的。由于MainActivity类的onCreate函数是在应用程序的主线程中被调用的,因此,这个handler参数就是和应用程序主线程的消息循环关联在一起的。在后面我们分析数据更新通知的发送过程时,便会看到这个handler参数是如何使用的了。
        下面我们就开始分析注册ArticleObserver来监控ActiclesProvider中的数据变化的过程,首先来看一下这个过程的时序图,然后再详细分析每一个步骤: