日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > Android >内容正文

Android

Android应用程序组件Content Provider在应用程序之间共享数据的原理分析(2)

發(fā)布時間:2023/12/31 Android 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Android应用程序组件Content Provider在应用程序之间共享数据的原理分析(2) 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
?? ?Step 7.?ContentProviderProxy.query ?? ? ?這個函數(shù)定義在frameworks/base/core/java/android/content/ContentProviderNative.java文件中:
  • final?class?ContentProviderProxy?implements?IContentProvider?{??
  • ????......??
  • ??
  • ????public?Cursor?query(Uri?url,?String[]?projection,?String?selection,??
  • ????????????String[]?selectionArgs,?String?sortOrder)?throws?RemoteException?{??
  • ????????//TODO?make?a?pool?of?windows?so?we?can?reuse?memory?dealers??
  • ????????CursorWindow?window?=?new?CursorWindow(false?/*?window?will?be?used?remotely?*/);??
  • ????????BulkCursorToCursorAdaptor?adaptor?=?new?BulkCursorToCursorAdaptor();??
  • ????????IBulkCursor?bulkCursor?=?bulkQueryInternal(??
  • ????????????url,?projection,?selection,?selectionArgs,?sortOrder,??
  • ????????????adaptor.getObserver(),?window,??
  • ????????????adaptor);??
  • ????????if?(bulkCursor?==?null)?{??
  • ????????????return?null;??
  • ????????}??
  • ????????return?adaptor;??
  • ????}??
  • ??
  • ????......??
  • }??
  • ?? ? ? ?這個函數(shù)首先會創(chuàng)建一個CursorWindow對象,前面已經(jīng)說過,這個CursorWindow對象包含了一塊匿名共享內(nèi)存,它的作用是把這塊匿名共享內(nèi)存通過Binder進程間通信機制傳給Content Proivder,好讓Content Proivder在里面返回所請求的數(shù)據(jù)。下面我們就先看看這個CursorWindow對象的創(chuàng)建過程,重點關注它是如何在內(nèi)部創(chuàng)建匿名共享內(nèi)存的,然后再回過頭來看看它調(diào)用bulkQueryInternal函數(shù)來做了些什么事情。 ?? ? ? ?CursorWindow類定義在frameworks/base/core/java/android/database/CursorWindow.java文件中,我們來看看它的構造函數(shù)的實現(xiàn):
  • public?class?CursorWindow?extends?SQLiteClosable?implements?Parcelable?{??
  • ????......??
  • ??
  • ????private?int?nWindow;??
  • ??
  • ????......??
  • ??
  • ????public?CursorWindow(boolean?localWindow)?{??
  • ????????......??
  • ??
  • ????????native_init(localWindow);??
  • ????}??
  • ??
  • ????......??
  • }??
  • ? ?? ? ? ?它主要調(diào)用本地方法native_init來執(zhí)行初始化的工作,主要就是創(chuàng)建匿名共享內(nèi)存了,傳進來的參數(shù)localWindow為false,表示這個匿名共享內(nèi)存只能通過遠程調(diào)用來訪問,即前面我們所說的,通過Content Proivder返回來的Cursor接口來訪問這塊匿名共享內(nèi)存里面的數(shù)據(jù)。 ?? ? ? ?Step 8. CursorWindow.native_init ?? ? ? ?這是一個JNI方法,它對應定義在frameworks/base/core/jni/android_database_CursorWindow.cpp文件中的native_init_empty函數(shù):
  • static?JNINativeMethod?sMethods[]?=??
  • {??
  • ?????/*?name,?signature,?funcPtr?*/??
  • ????{"native_init",?"(Z)V",?(void?*)native_init_empty},??
  • ????......??
  • };??
  • ?? ? ? ? 函數(shù)native_init_empty的定義如下所示:
  • static?void?native_init_empty(JNIEnv?*?env,?jobject?object,?jboolean?localOnly)??
  • {??
  • ????......??
  • ??
  • ????CursorWindow?*?window;??
  • ??
  • ????window?=?new?CursorWindow(MAX_WINDOW_SIZE);??
  • ????......??
  • ??
  • ????if?(!window->initBuffer(localOnly))?{??
  • ????????......??
  • ????}??
  • ??
  • ????......??
  • ????SET_WINDOW(env,?object,?window);??
  • }??
  • ?? ? ? ? 這個函數(shù)在C++層創(chuàng)建了一個CursorWindow對象,然后通過調(diào)用SET_WINDOW宏來把這個C++層的CursorWindow對象與Java層的CursorWindow對象關系起來:
  • #define?SET_WINDOW(env,?object,?window)?(env->SetIntField(object,?gWindowField,?(int)window))??
  • ?? ? ? ? 這里的gWindowField即定義為Java層的CursorWindow對象中的nWindow成員變量:
  • static?jfieldID?gWindowField;??
  • ??
  • ......??
  • ??
  • int?register_android_database_CursorWindow(JNIEnv?*?env)??
  • {??
  • ????jclass?clazz;??
  • ??
  • ????clazz?=?env->FindClass("android/database/CursorWindow");??
  • ????......??
  • ??
  • ????gWindowField?=?env->GetFieldID(clazz,?"nWindow",?"I");??
  • ??
  • ????......??
  • }??
  • ?? ? ? ?這種用法在Android應用程序框架層中非常普遍。 ? ?? ? ? ?下面我們重點關注C++層的CursorWindow對象的initBuffer函數(shù)的實現(xiàn)。 ?? ? ? ?Step 9.?CursorWindow.initBuffer ?? ? ? ?C++層的CursorWindow類定義在frameworks/base/core/jni/CursorWindow.cpp文件中:
  • bool?CursorWindow::initBuffer(bool?localOnly)??
  • {??
  • ????......??
  • ??
  • ????sp<MemoryHeapBase>?heap;??
  • ????heap?=?new?MemoryHeapBase(mMaxSize,?0,?"CursorWindow");??
  • ????if?(heap?!=?NULL)?{??
  • ????????mMemory?=?new?MemoryBase(heap,?0,?mMaxSize);??
  • ????????if?(mMemory?!=?NULL)?{??
  • ????????????mData?=?(uint8_t?*)?mMemory->pointer();??
  • ????????????if?(mData)?{??
  • ????????????????mHeader?=?(window_header_t?*)?mData;??
  • ????????????????mSize?=?mMaxSize;??
  • ??
  • ????????????????......??
  • ????????????}??
  • ????????}??
  • ????????......??
  • ????}?else?{??
  • ????????......??
  • ????}??
  • }??
  • ?? ? ? ?這里我們就可以很清楚地看到,在CursorWindow類的內(nèi)部有一個成員變量mMemory,它的類型是MemoryBase。MemoryBase類為我們封裝了匿名共享內(nèi)存的訪問以及在進程間的傳輸?shù)葐栴},具體可以參考前面一篇文章Android系統(tǒng)匿名共享內(nèi)存(Anonymous Shared Memory)C++調(diào)用接口分析,這里就不再詳述了。 ? ?? ? ? ?通過Step 8和Step 9兩步,用來在第三方應用程序和Content Provider之間傳輸數(shù)據(jù)的媒介就準備好了,我們回到Step 7中,看看系統(tǒng)是如何把這個匿名共享存?zhèn)鬟f給Content Provider使用的。在Step 7中,最后調(diào)用bulkQueryInternal函數(shù)來進一步操作。 ?? ? ? ?Step 10.?ContentProviderProxy.bulkQueryInternal ?? ? ?這個函數(shù)定義在frameworks/base/core/java/android/content/ContentProviderNative.java文件中:
  • final?class?ContentProviderProxy?implements?IContentProvider???
  • {???
  • ????......???
  • ???
  • ????private?IBulkCursor?bulkQueryInternal(???
  • ????????????Uri?url,?String[]?projection,???
  • ????????????String?selection,?String[]?selectionArgs,?String?sortOrder,???
  • ????????????IContentObserver?observer,?CursorWindow?window,???
  • ????????????BulkCursorToCursorAdaptor?adaptor)?throws?RemoteException?{???
  • ????????Parcel?data?=?Parcel.obtain();???
  • ????????Parcel?reply?=?Parcel.obtain();???
  • ???
  • ????????data.writeInterfaceToken(IContentProvider.descriptor);???
  • ???
  • ????????url.writeToParcel(data,?0);???
  • ????????int?length?=?0;???
  • ????????if?(projection?!=?null)?{???
  • ????????????length?=?projection.length;???
  • ????????}???
  • ????????data.writeInt(length);???
  • ????????for?(int?i?=?0;?i?<?length;?i++)?{???
  • ????????????data.writeString(projection[i]);???
  • ????????}???
  • ????????data.writeString(selection);???
  • ????????if?(selectionArgs?!=?null)?{???
  • ????????????length?=?selectionArgs.length;???
  • ????????}?else?{???
  • ????????????length?=?0;???
  • ????????}???
  • ????????data.writeInt(length);???
  • ????????for?(int?i?=?0;?i?<?length;?i++)?{???
  • ????????????data.writeString(selectionArgs[i]);???
  • ????????}???
  • ????????data.writeString(sortOrder);???
  • ????????data.writeStrongBinder(observer.asBinder());???
  • ????????window.writeToParcel(data,?0);???
  • ???
  • ????????//?Flag?for?whether?or?not?we?want?the?number?of?rows?in?the???
  • ????????//?cursor?and?the?position?of?the?"_id"?column?index?(or?-1?if???
  • ????????//?non-existent).??Only?to?be?returned?if?binder?!=?null.???
  • ????????final?boolean?wantsCursorMetadata?=?(adaptor?!=?null);???
  • ????????data.writeInt(wantsCursorMetadata???1?:?0);???
  • ???
  • ????????mRemote.transact(IContentProvider.QUERY_TRANSACTION,?data,?reply,?0);???
  • ???
  • ????????DatabaseUtils.readExceptionFromParcel(reply);???
  • ???
  • ????????IBulkCursor?bulkCursor?=?null;???
  • ????????IBinder?bulkCursorBinder?=?reply.readStrongBinder();???
  • ????????if?(bulkCursorBinder?!=?null)?{???
  • ????????????bulkCursor?=?BulkCursorNative.asInterface(bulkCursorBinder);???
  • ???
  • ????????????if?(wantsCursorMetadata)?{???
  • ????????????????int?rowCount?=?reply.readInt();???
  • ????????????????int?idColumnPosition?=?reply.readInt();???
  • ????????????????if?(bulkCursor?!=?null)?{???
  • ????????????????????adaptor.set(bulkCursor,?rowCount,?idColumnPosition);???
  • ????????????????}???
  • ????????????}???
  • ????????}???
  • ???
  • ????????data.recycle();???
  • ????????reply.recycle();???
  • ???
  • ????????return?bulkCursor;???
  • ????}???
  • ???
  • ????......???
  • }???
  • ? ? ?這個函數(shù)有點長,不過它的邏輯很簡單,就是把查詢參數(shù)都寫到一個Parcel對象data中去,然后通過下面Binder進程間通信機制把查詢請求傳給Content Provider處理:?
  • mRemote.transact(IContentProvider.QUERY_TRANSACTION,?data,?reply,?0);??
  • ?? ? ?從這個Binder調(diào)用返回以后,就會得到一個IBulkCursor接口,它是一個Binder引用,實際是指向在Content Provider這一側(cè)創(chuàng)建的一個CursorToBulkCursorAdaptor對象,后面我們將會看到。有了這個IBulkCursor接口之后,我們就可以通過Binder進程間調(diào)用來訪問從Content Provider中查詢得到的數(shù)據(jù)了。這個IBulkCursor接口最終最設置了上面Step 7中創(chuàng)建的BulkCursorToCursorAdaptor對象adaptor中去:
  • adaptor.set(bulkCursor,?rowCount,?idColumnPosition);??
  • ?? ? ?BulkCursorToCursorAdaptor類實現(xiàn)了Cursor接口,因此,我們可以通過Curosr接口來訪問這些查詢得到的共享數(shù)據(jù)。 ? ? ? 在前面把查詢參數(shù)寫到Parcel對象data中去的過程中,有兩個步驟是比較重要的,分別下面這段執(zhí)行語句:
  • window.writeToParcel(data,?0);??
  • ??
  • //?Flag?for?whether?or?not?we?want?the?number?of?rows?in?the??
  • //?cursor?and?the?position?of?the?"_id"?column?index?(or?-1?if??
  • //?non-existent).??Only?to?be?returned?if?binder?!=?null.??
  • final?boolean?wantsCursorMetadata?=?(adaptor?!=?null);??
  • data.writeInt(wantsCursorMetadata???1?:?0);??
  • ?? ? ?調(diào)用window.writeToParcel是把window對象內(nèi)部的匿名共享內(nèi)存塊通過Binder進程間通信機制傳輸給Content Provider來使用;而當傳進來的參數(shù)adaptor不為null時,就會往data中寫入一個整數(shù)1,表示讓Content Provider把查詢得到數(shù)據(jù)的元信息一起返回來,例如數(shù)據(jù)的行數(shù)、數(shù)據(jù)行的ID列的索引位置等信息,這個整數(shù)值會促使Content Provider把前面說的IBulkCursor接口返回給第三方應用程序之前,真正執(zhí)行一把數(shù)據(jù)庫查詢操作,后面我們將看到這個過程。 ? ? ? 現(xiàn)在,我們重點來關注一下CursorWindow類的writeToParcel函數(shù),看看它是如何把它內(nèi)部的匿名共享內(nèi)存對象寫到數(shù)據(jù)流data中去的。

    轉(zhuǎn)載于:https://blog.51cto.com/shyluo/966999

    總結(jié)

    以上是生活随笔為你收集整理的Android应用程序组件Content Provider在应用程序之间共享数据的原理分析(2)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。