Step 11. CursorWindow.writeToParcel 这个函数定义在frameworks/base/core/java/android/database/CursorWindow.java文件中:
  1. publicclassCursorWindowextendsSQLiteClosableimplementsParcelable{
  2. ......
  3. publicvoidwriteToParcel(Parceldest,intflags){
  4. ......
  5. dest.writeStrongBinder(native_getBinder());
  6. ......
  7. }
  8. ......
  9. }
这个函数最主要的操作就是往数据流dest写入一个Binder对象,这个Binder对象是通过调用本地方法native_getBinder来得到的。 Step 12. CursorWindow.native_getBinder 这个函数定义在frameworks/base/core/jni/android_database_CursorWindow.cpp文件中:
  1. staticjobjectnative_getBinder(JNIEnv*env,jobjectobject)
  2. {
  3. CursorWindow*window=GET_WINDOW(env,object);
  4. if(window){
  5. sp<IMemory>memory=window->getMemory();
  6. if(memory!=NULL){
  7. sp<IBinder>binder=memory->asBinder();
  8. returnjavaObjectForIBinder(env,binder);
  9. }
  10. }
  11. returnNULL;
  12. }
在前面的Step 8中,我们在C++层创建了一个CursorWindow对象,这个对象保存在Java层创建的CursorWindow对象的成员变量nWindow中,这里通过GET_WINDOW宏来把这个在C++层创建的CurosrWindow对象返回来:
  1. #defineGET_WINDOW(env,object)((CursorWindow*)env->GetIntField(object,gWindowField))
获得了这个CursorWindow对象以后,就调用它的getMemory函数来获得一个IMemory接口,这是一个Binder接口,具体可以参考前面一篇文章 Android系统匿名共享内存(Anonymous Shared Memory)C++调用接口分析 Step 13. CursorWindow.getMemory 这个函数定义在frameworks/base/core/jni/CursorWindow.h文件中:
  1. classCursorWindow
  2. {
  3. public:
  4. ......
  5. sp<IMemory>getMemory(){returnmMemory;}
  6. ......
  7. }
这个CursorWindow对象的成员变量mMemory就是在前面Step 9中创建的了。 这样,在第三方应用程序这一侧创建的匿名共享存对象就可以传递给Content Provider来使用了。回到前面的Step 10中,所有的参数都就准备就绪以后,就通过Binder进程间通信机制把数据查询请求发送给相应的Content Proivder了。这个请求是在ContentProviderNative类的onTransact函数中响应的。 Step 14.ContentProviderNative.onTransact 这个函数定义在frameworks/base/core/java/android/content/ContentProviderNative.java文件中:
        
  1. abstractpublicclassContentProviderNativeextendsBinderimplementsIContentProvider{
  2. ......
  3. @Override
  4. publicbooleanonTransact(intcode,Parceldata,Parcelreply,intflags)
  5. throwsRemoteException{
  6. try{
  7. switch(code){
  8. caseQUERY_TRANSACTION:
  9. {
  10. data.enforceInterface(IContentProvider.descriptor);
  11. Uriurl=Uri.CREATOR.createFromParcel(data);
  12. //String[]projection
  13. intnum=data.readInt();
  14. String[]projection=null;
  15. if(num>0){
  16. projection=newString[num];
  17. for(inti=0;i<num;i++){
  18. projection[i]=data.readString();
  19. }
  20. }
  21. //Stringselection,String[]selectionArgs...
  22. Stringselection=data.readString();
  23. num=data.readInt();
  24. String[]selectionArgs=null;
  25. if(num>0){
  26. selectionArgs=newString[num];
  27. for(inti=0;i<num;i++){
  28. selectionArgs[i]=data.readString();
  29. }
  30. }
  31. StringsortOrder=data.readString();
  32. IContentObserverobserver=IContentObserver.Stub.
  33. asInterface(data.readStrongBinder());
  34. CursorWindowwindow=CursorWindow.CREATOR.createFromParcel(data);
  35. //Flagforwhethercallerwantsthenumberof
  36. //rowsinthecursorandthepositionofthe
  37. //"_id"columnindex(or-1ifnon-existent)
  38. //Onlytobereturnedifbinder!=null.
  39. booleanwantsCursorMetadata=data.readInt()!=0;
  40. IBulkCursorbulkCursor=bulkQuery(url,projection,selection,
  41. selectionArgs,sortOrder,observer,window);
  42. reply.writeNoException();
  43. if(bulkCursor!=null){
  44. reply.writeStrongBinder(bulkCursor.asBinder());
  45. if(wantsCursorMetadata){
  46. reply.writeInt(bulkCursor.count());
  47. reply.writeInt(BulkCursorToCursorAdaptor.findRowIdColumnIndex(
  48. bulkCursor.getColumnNames()));
  49. }
  50. }else{
  51. reply.writeStrongBinder(null);
  52. }
  53. returntrue;
  54. }
  55. ......
  56. }
  57. }catch(Exceptione){
  58. DatabaseUtils.writeExceptionToParcel(reply,e);
  59. returntrue;
  60. }
  61. returnsuper.onTransact(code,data,reply,flags);
  62. }
  63. ......
  64. }
这一步其实就是前面Step 10的逆操作,把请求参数从数据流data中读取出来。这里我们同样是重点关注下面这两个参数读取的步骤:
  1. CursorWindowwindow=CursorWindow.CREATOR.createFromParcel(data);
  2. //Flagforwhethercallerwantsthenumberof
  3. //rowsinthecursorandthepositionofthe
  4. //"_id"columnindex(or-1ifnon-existent)
  5. //Onlytobereturnedifbinder!=null.
  6. booleanwantsCursorMetadata=data.readInt()!=0;
通过调用CursorWindow.CREATOR.createFromParcel函数来从数据流data中重建一个本地的CursorWindow对象;接着又将数据流data的下一个整数值读取出来,如果这个整数值不为0,变量wantsCursorMetadata的值就为true,说明Content Provider在返回IBulkCursor接口给第三方应用程序之前,要先实际执行一把数据库查询操作,以便把结果数据的元信息返回给第三方应用程序。 通过下面的代码我们可以看到,调用bulkQuery函数之后,就得到了一个IBulkCursor接口,这表示要返回的数据准备就绪了,但是这时候实际上还没有把结果数据从数据库中提取出来,而只是准备好了一个SQL查询计划,等到真正要使用这些结果数据时,系统才会真正执行查询数据库的操作:
  1. if(wantsCursorMetadata){
  2. reply.writeInt(bulkCursor.count());
  3. ......
  4. }
在将这个IBulkCursor接口返回给第三方应用程序之前,如果发现wantsCursorMetadata的值就为true,就会调用它的count函数来获得结果数据的总行数,这样就会导致系统真正去执行数据库查询操作,并把结果数据保存到前面得到的CursorWindow对象中的匿名共享内存中去。 下面我们就重点关注CursorWindow.CREATOR.createFromParcel函数是如何从数据流data中在本地构造一个CursorWindow对象的。 Step 15.CursorWindow.CREATOR.createFromParcel 这个函数定义在frameworks/base/core/java/android/database/CursorWindow.java文件中:
  1. publicclassCursorWindowextendsSQLiteClosableimplementsParcelable{
  2. ......
  3. privateCursorWindow(Parcelsource){
  4. IBindernativeBinder=source.readStrongBinder();
  5. ......
  6. native_init(nativeBinder);
  7. }
  8. ......
  9. publicstaticfinalParcelable.Creator<CursorWindow>CREATOR
  10. =newParcelable.Creator<CursorWindow>(){
  11. publicCursorWindowcreateFromParcel(Parcelsource){
  12. returnnewCursorWindow(source);
  13. }
  14. ......
  15. };
  16. ......
  17. }
在创建CursorWindow对象的过程中,首先是从数据流source中将在前面Step 10中写入的Binder接口读取出来,然后使用这个Binder接口来初始化这个CursorWindow对象,通过前面的Step 13,我们知道,这个Binder接口的实际类型为IMemory,它封装了对匿名共享内存的访问操作。初始化这个匿名共享内存对象的操作是由本地方法native_init函数来实现的,下面我们就看看它的实现。

更多相关文章

  1. 箭头函数的基础使用
  2. 类和 Json对象
  3. Python技巧匿名函数、回调函数和高阶函数
  4. Android中,把XML文件转换成Object对象的方法
  5. Android(安卓)Bundle类
  6. View机制深入学习(一)
  7. Android传感器
  8. Android应用程序绑定服务(bindService)的过程源代码分析(2)
  9. Android中话bitmap的简单示例

随机推荐

  1. Android联系人数据库全解析(5)
  2. android layouts之RelativeLayout
  3. react-native APP图标和Splash(Android)
  4. 移植android的工作环境
  5. 2015-10-30-02-Android Theme主题使用心
  6. Android 重力感应 翻转页面造成Activity
  7. android ListView向下展开 抽屉效果
  8. android 关于字符转化问题
  9. Android文档-开发者指南-第一部分:入门-中
  10. Android 基于UDP的Socket通信