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. Android中,把XML文件转换成Object对象的方法
  2. 初学Android,五大布局对象(六)
  3. Android中intent传递对象和Bundle的用法
  4. C语言函数以及函数的使用
  5. 理解Android回调函数
  6. Android 基本属性绘制文本对象FontMetrics介绍
  7. Android Camera 数据流
  8. android Activity之间传递对象
  9. FregClient进程,创建一个BpFregService类型的代理对象

随机推荐

  1. Android设备adb授权的原理
  2. Android PinnedSectionListView 收缩
  3. Android(安卓)如何编写基于编译时注解的
  4. Android中万能适配器
  5. Android Uri
  6. Android——permission之android:protect
  7. 为什么Android的Adapter中,bindview被调用
  8. Android(安卓)JNI入门第二篇――Java参数
  9. android 增加鼠标事件
  10. Android(安卓)通过zygote来运行java程序