Step 1. ContentResolver.registerContentObserver 这个函数定义在frameworks/base/core/java/android/content/ContentResolver.java文件中:
        
  1. publicabstractclassContentResolver{
  2. ......
  3. publicfinalvoidregisterContentObserver(Uriuri,booleannotifyForDescendents,
  4. ContentObserverobserver)
  5. {
  6. try{
  7. getContentService().registerContentObserver(uri,notifyForDescendents,
  8. observer.getContentObserver());
  9. }catch(RemoteExceptione){
  10. }
  11. }
  12. ......
  13. }
当参数notifyForDescendents为true时,表示要监控所有以uri为前缀的URI对应的数据变化。这个函数做了三件事情,一是调用getContentService函数来获得前面已经启动起来了的ContentService远程接口,二是调用从参数传进来的ContentObserver对象observer的getContentObserver函数来获得一个Binder对象,三是通过调用这个ContentService远程接口的registerContentObserver函数来把这个Binder对象注册到ContentService中去。

Step 2.ContentResolver.getContentService 这个函数定义在frameworks/base/core/java/android/content/ContentResolver.java文件中:
        
  1. publicabstractclassContentResolver{
  2. ......
  3. publicstaticIContentServicegetContentService(){
  4. if(sContentService!=null){
  5. returnsContentService;
  6. }
  7. IBinderb=ServiceManager.getService(CONTENT_SERVICE_NAME);
  8. ......
  9. sContentService=IContentService.Stub.asInterface(b);
  10. ......
  11. returnsContentService;
  12. }
  13. privatestaticIContentServicesContentService;
  14. ......
  15. }

在ContentResolver类中,有一个静态成员变量sContentService,开始时它的值为null。当ContentResolver类的getContentService函数第一次被调用时,它便会通过ServiceManager类的getService函数来获得前面已经启动起来了的ContentService服务的远程接口,然后把它保存在sContentService变量中。这样,当下次ContentResolver类的getContentService函数再次被调用时,就可以直接把这个ContentService远程接口返回给调用者了。

Step 3.ContentObserver.getContentObserver 这个函数定义在frameworks/base/core/java/android/database/ContentObserver.java文件中:
        
  1. publicabstractclassContentObserver{
  2. ......
  3. privateTransportmTransport;
  4. ......
  5. privatestaticfinalclassTransportextendsIContentObserver.Stub{
  6. ContentObservermContentObserver;
  7. publicTransport(ContentObservercontentObserver){
  8. mContentObserver=contentObserver;
  9. }
  10. ......
  11. }
  12. ......
  13. publicIContentObservergetContentObserver(){
  14. synchronized(lock){
  15. if(mTransport==null){
  16. mTransport=newTransport(this);
  17. }
  18. returnmTransport;
  19. }
  20. }
  21. ......
  22. }

ContentObserver类的getContentObserver函数返回的是一个成员变量mTransport,它的类型为ContentObserver的内部类Transport。从Transport类的定义我们可以知道,它有一个成员变量mContentObserver,用来保存与对应的ContentObserver对象。同时我们还可以看出,ContentObserver类的成员变量mTransport是一个Binder对象,它是要传递给ContentService服务的,以便当ContentObserver所监控的数据发生变化时,ContentService服务可以通过这个Binder对象通知相应的ContentObserver它监控的数据发生变化了。

Step 4. ContentService.registerContentObserver 这个函数定义在frameworks/base/core/java/android/content/ContentService.java文件中:
        
  1. publicfinalclassContentServiceextendsIContentService.Stub{
  2. ......
  3. privatefinalObserverNodemRootNode=newObserverNode("");
  4. ......
  5. publicvoidregisterContentObserver(Uriuri,booleannotifyForDescendents,
  6. IContentObserverobserver){
  7. ......
  8. synchronized(mRootNode){
  9. mRootNode.addObserverLocked(uri,observer,notifyForDescendents,mRootNode);
  10. ......
  11. }
  12. }
  13. ......
  14. }

它调用了ContentService类的成员变量mRootNode的addObserverLocked函数来注册这个ContentObserver对象observer。成员变量mRootNode的类型为ContentService在内部定义的一个类ObserverNode。

Step 5.ObserverNode.addObserverLocked 这个函数定义在frameworks/base/core/java/android/content/ContentService.java文件中:
        
  1. publicfinalclassContentServiceextendsIContentService.Stub{
  2. ......
  3. publicstaticfinalclassObserverNode{
  4. ......
  5. privateStringmName;
  6. privateArrayList<ObserverNode>mChildren=newArrayList<ObserverNode>();
  7. privateArrayList<ObserverEntry>mObservers=newArrayList<ObserverEntry>();
  8. publicObserverNode(Stringname){
  9. mName=name;
  10. }
  11. privateStringgetUriSegment(Uriuri,intindex){
  12. if(uri!=null){
  13. if(index==0){
  14. returnuri.getAuthority();
  15. }else{
  16. returnuri.getPathSegments().get(index-1);
  17. }
  18. }else{
  19. returnnull;
  20. }
  21. }
  22. privateintcountUriSegments(Uriuri){
  23. if(uri==null){
  24. return0;
  25. }
  26. returnuri.getPathSegments().size()+1;
  27. }
  28. publicvoidaddObserverLocked(Uriuri,IContentObserverobserver,
  29. booleannotifyForDescendents,ObjectobserversLock){
  30. addObserverLocked(uri,0,observer,notifyForDescendents,observersLock);
  31. }
  32. privatevoidaddObserverLocked(Uriuri,intindex,IContentObserverobserver,
  33. booleannotifyForDescendents,ObjectobserversLock){
  34. //Ifthisistheleafnodeaddtheobserver
  35. if(index==countUriSegments(uri)){
  36. mObservers.add(newObserverEntry(observer,notifyForDescendents,observersLock));
  37. return;
  38. }
  39. //Looktoseeiftheproperchildalreadyexists
  40. Stringsegment=getUriSegment(uri,index);
  41. if(segment==null){
  42. thrownewIllegalArgumentException("InvalidUri("+uri+")usedforobserver");
  43. }
  44. intN=mChildren.size();
  45. for(inti=0;i<N;i++){
  46. ObserverNodenode=mChildren.get(i);
  47. if(node.mName.equals(segment)){
  48. node.addObserverLocked(uri,index+1,observer,notifyForDescendents,observersLock);
  49. return;
  50. }
  51. }
  52. //Nochildfound,createone
  53. ObserverNodenode=newObserverNode(segment);
  54. mChildren.add(node);
  55. node.addObserverLocked(uri,index+1,observer,notifyForDescendents,observersLock);
  56. }
  57. ......
  58. }
  59. ......
  60. }

从这里我们就可以看出,注册到ContentService中的ContentObserver按照树形来组织,树的节点类型为ObserverNode,而树的根节点就为ContentService类的成员变量mRootNode。每一个ObserverNode节点都对应一个名字,它是从URI中解析出来的。

在我们这个情景中,传进来的uri为"content://shy.luo.providers.articles/item",从Step 3调用mRootNode的addObserverLocked函数来往树上增加一个ObserverNode节点时,传进来的参数index的值为0,而调用countUriSegments("content://shy.luo.providers.articles/item")函数的返回值为2,不等于index的值,因此就会往下执行,而通过调用getUriSegment("content://shy.luo.providers.articles/item", 0)函数得到的返回值为"shy.luo.providers.articles"。假设这里是第一次调用树的根节点mRootNode来增加"content://shy.luo.providers.articles/item"这个URI,那么在接下来的for循环中,就不会在mRootNode的孩子节点列表mChildren中找到与名称"shy.luo.providers.articles"对应的ObserverNode,于是就会以"shy.luo.providers.articles"为名称来创建一个新的ObserverNode,并增加到mRootNode的孩子节点列表mChildren中去,并以这个新的ObserverNode来开始新一轮的addObserverLocked函数调用。 第二次进入到addObserverLocked函数时,countUriSegments("content://shy.luo.providers.articles/item")的值仍为2,而index的值为1,因此就会往下执行,这时候通过调用getUriSegment("content://shy.luo.providers.articles/item", 1)函数得到的返回值为"item"。假设这时候在以"shy.luo.providers.articles/item"为名称的ObserverNode中不存在名称为"item"的孩子节点,于是又会以"item"为名称来创建一个新的ObserverNode,并以这个新的ObserverNode来开始新一轮的addObserverLocked函数调用。 第三次进入到addObserverLocked函数时,countUriSegments("content://shy.luo.providers.articles/item")的值仍为2,而index的值也为2,因此就会新建一个ObserverEntry对象,并保存在这个以"item"为名称的ObserverNode的ContentObserver列表mObervers中。 最终我们得到的树形结构如下所示: mRootNode("") -- ObserverNode("shy.luo.providers.articles") --ObserverNode("item") , which has a ContentObserver in mObservers
这样,ContentObserver的注册过程就完成了。

更多相关文章

  1. How to destroy an Activity in android
  2. Android中获取屏幕信息DisplayMetrics的用法
  3. Android应用程序键盘(Keyboard)消息处理机制分析(21)
  4. Android(安卓)Universal Image Loader 源码分析
  5. android framework
  6. 2011.09.22——— android ViewStub的简单使用
  7. Android应用程序组件Content Provider的启动过程源代码分析(6)
  8. android的TextUtils.substring与.net的不同点
  9. Android系统进程Zygote启动过程的源代码分析(3)

随机推荐

  1. 学习PHP-cli 模式在终端输出彩色标记文字
  2. 一起看看PHP设计模式之适配器模式
  3. 了解PHP yield的高级用法
  4. Go与PHP的语法是如何对比
  5. php 异常处理有什么用?
  6. 分享一个PHP写的命令行音乐搜索下载器
  7. 关于PHP进程防止内存溢出的排查
  8. php模拟qq登录代码
  9. php base64如何进行URL字符串编码和解码?
  10. PHP实现长轮询【代码示例】