全國工程信息網(wǎng)優(yōu)化方案怎么寫
學更好的別人,
做更好的自己。
——《微卡智享》
本文長度為2478字,預計閱讀6分鐘
前言
Android的AIDL使用和異常報錯都已經(jīng)介紹過了,今天這篇還是在原來的Demo基礎上加入幾個AIDL的進階使用方法。
】
AIDL進階使用

微卡智享
in,out,inout的使用
關于in,out,inout在AIDL的基礎介紹中有提到過
AIDL中還有定向的Tag,包括了in、out、inout。其中 in 表示數(shù)據(jù)只能由客戶端流向服務端, out 表示數(shù)據(jù)只能由服務端流向客戶端,而 inout 則表示數(shù)據(jù)可在服務端與客戶端之間雙向流通。
Vaccae,公眾號:微卡智享Android Aidl跨進程通訊的簡單使用
根據(jù)字面意思可以很簡單的理解,所以我們直接做一個函數(shù)實現(xiàn)inout的方法即可。
-
在服務端的Aidl文件中加入一個新的函數(shù)updateTestDatsList,輸入的參數(shù)設置為inout
-
Build后在Service的object : ITestDataAidlInterface.Stub()里面寫入實現(xiàn),這里我們先將傳入的list里面再自定義加入一條,然后插入到Service緩存的List列表中,再將傳入的listdata清空后,把Service緩存中的所有數(shù)據(jù)都插入傳入的listdata
-
因為是跨進程,所以客戶端需要將修改后的Aidl復制過來替換原來的,然后在MainActivity中寫入實現(xiàn)調用
運行效果
點擊更新列表后的對比,可以看到,使用inout參數(shù),傳入的list最后也已經(jīng)修改完成。
AIDL使用Bundle傳遞多個數(shù)據(jù)
AIDL可以使用Bundle類封裝通訊數(shù)據(jù),用于傳遞一些復雜的對象或者多個對象。
Bundle類是一個鍵值對的容器,它可以存儲不同類型的數(shù)據(jù),并且實現(xiàn)了Parcelable接口,所以可以在進程間傳輸。
-
Service的AIDL接口加入新的函數(shù)transBundle,傳入的參數(shù)就是Bundle
-
在Service加入接口實現(xiàn),這里我們測試里面加入一個Float,一個Int,和一個List數(shù)據(jù),將原來的價格和數(shù)量都統(tǒng)一改為一樣的數(shù)據(jù)后,再將傳入的list加入到后面,最后展現(xiàn)出來,
劃重點
Android有兩種不同的classloaders:framework classloader和apk classloader,其中framework classloader知道怎么加載android classes,apk classloader繼承自framework classloader,所以也知道怎么加載android classes。但在應用剛啟動時,默認class loader是apk classloader,在系統(tǒng)內存不足應用被系統(tǒng)回收會再次啟動,這個默認class loader會變?yōu)閒ramework classloader了,所以對于自己的類會報ClassNotFoundException,就會出現(xiàn)android.os.BadParcelableException: ClassNotFoundException when unmarshalling
所以在bundle數(shù)據(jù)讀取前,先設置classloader后,才能正確地讀取自定義類
it.classLoader = TestData::class.java.classLoader
override fun transBundle(bundle: Bundle?): MutableList<TestData> {bundle?.let { it ->/*Android有兩種不同的classloaders:framework classloader和apk classloader,其中framework classloader知道怎么加載android classes,apk classloader繼承自framework classloader,所以也知道怎么加載android classes。但在應用剛啟動時,默認class loader是apk classloader,在系統(tǒng)內存不足應用被系統(tǒng)回收會再次啟動,這個默認class loader會變?yōu)閒ramework classloader了,所以對于自己的類會報ClassNotFoundException就會出現(xiàn)android.os.BadParcelableException: ClassNotFoundException when unmarshalling*///所以在bundle數(shù)據(jù)讀取前,先設置classloader后,才能正確的讀取自定義類it.classLoader = TestData::class.java.classLoaderval price = it.getFloat("price")val qty = it.getInt("qty")mTestDatas.map { t->t.price = pricet.qty = qty}val list = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {it.getParcelableArrayList("listdatas", TestData::class.java)} else {it.getParcelableArrayList<TestData>("listdatas")}list?.let { item->mTestDatas.addAll(item)}}return mTestDatas}
-
客戶端中一樣要把AIDL復制過來后,寫實現(xiàn)方法
運行效果
關于oneway關鍵字
AIDL中的oneway關鍵字,主要用來使IPC調用變成非阻塞的。
oneway需要注意的幾點:
-
將遠程調用改為異步調用,使得遠程調用變成非阻塞式的,客戶端不需要等待服務端的處理,只是發(fā)送數(shù)據(jù)并立即返回。要注意的是,oneway修飾本地調用沒有效果,仍然是同步的,客戶端需要等待服務端的處理。
-
在同一個IBinder對象調用中,會按照調用順序依次執(zhí)行,不同的IBinder對象可能導致調用順序和執(zhí)行順序不一致。
-
oneway不能帶有返回值或拋出異常,因為客戶端是無法接收的。
Demo源碼中也已經(jīng)更新上傳了。
源碼地址
https://github.com/Vaccae/AndroidAIDLDemo.git
點擊原文鏈接可以看到“碼云”的源碼地址
完
往期精彩回顧
?
Android Aidl跨進程通訊(二)--異常捕獲處理
??
Android Aidl跨進程通訊的簡單使用
??
Android BlueToothBLE入門(三)——數(shù)據(jù)的分包發(fā)送和接收(源碼已更新)
??
?