Android進程間通信(1)

IPC(Inter-Process Communication)進程間通信,就是指在兩個進程之間進行數(shù)據(jù)交換的過程。那么就要先了解什么是進程,什么是線程。從一定意義上講,進程就是一個應用程序在處理機上的一次執(zhí)行過程,它是一個動態(tài)的概念,而線程是進程中的一部分,進程包含多個線程在運行。即一個進程可以包括多個線程,也可以只有一個線程。

現(xiàn)在我們學習進程間通信中使用到的兩個重要接口:

Serializable接口:Serializable可序列化的,實現(xiàn)了這個接口的類,可以通過IO流讀寫對象,可以實現(xiàn)對象的序列化和反序列化。事實上這個接口是一個空接口,就是一個標識,我們在創(chuàng)建類的時候,如果想要這個類型的對象可以序列化和反序列,只需要實現(xiàn)這個接口就可,同時也可以指定serialVersionUID(其實可以不需要,這個可能會對反序列早成影響)public static final long serialVersionUID = 1L。如果寫了serialVersionUID那么在反序化的時候就會比較文件中的這個值和當前類的值是否相等,如果一致,則會反序列成功,反之,則會拋出異常。

Parceable接口:可打包的接口,一個類實現(xiàn)了這個接口,也可以實現(xiàn)序列化,并且可以同Intent和Binder傳遞。現(xiàn)在看看Parceable接口里面的方法:
createFromParcel(Parcel in)從序列化后的對象中創(chuàng)建原始對象。? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? newArray(int size) 創(chuàng)建指定長度的原始對象數(shù)組。? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? User(Parcel in)從序列化后的對象創(chuàng)建原始對象。? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? writeToParcel(Parcel out,int flags)將當前對象寫入序列化結(jié)構(gòu)中,其中flags標識有兩中值0或者1,為1時標識當前對象需要作為返回值返回,不立即釋放資源,幾乎所有的情況都是0 PARCELABLE_WRITE_REYURN_BALUE? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? describeContents()返回當前對象內(nèi)容描述,如果含有文件描述符,返回1,否則返回0 CONTENTS_FILE_DESCRIPTOR

Parceable接口和Serializable接口區(qū)別:Serializable是java中的序列化接口,其使用簡單但是開銷很大,在序列化和反序列化中需要大量的IO操作,Parceable是Android中的序列化接口,更加適用于Android平臺,雖然使用麻煩不過效率高,其主要是在內(nèi)存上序列化,如果將對象序列化到存儲設備或者將對象序列化后通過網(wǎng)絡傳輸,這兩種情況Serializable就比Parceable更加適合。

IPC進程間通信:

AIDL:Android Interface definition language Android接口定義語言,是以Binder為基礎的一種進程間通信。

我們先了解是是Binder:是Android中的一個類,實現(xiàn)了IBinder接口,可以理解為一種虛擬的物理設備,是ServiceManager鏈接各種Manager(ActivityManager,WindowManager)和相應ManagerService的橋梁,從Android應用層來說,是客戶端和服務端進行通信的媒介,當bindService的時候,服務端會返回一個包含了服務端業(yè)務調(diào)用的Binder對象,通過調(diào)用這個Binder對象,客戶端可以獲取服務端提供的服務或者數(shù)據(jù)。

Binder中的一些字段和方法:

DESCRIPTOR:Binder標識符一般是用包名。

asInterface(IBinder obj);用于將服務端的Binder對象轉(zhuǎn)換成客戶端所需要的AIDL接口類型,轉(zhuǎn)換是區(qū)分進程的,如果是同進程則返回服務端Stub本身,反之則是系統(tǒng)分裝后的Stub.proxy對象

asBinder();返回Binder本身

onTransact(int code,Pracel data,Pracel reply,int flags):服務端通過code來判斷客戶端請求的目標方法是什么,接著從data中取出目標方法所需要的參數(shù),執(zhí)行,然后在想reply寫入返回值。如果onTransact()返回false,那么客戶端請求就會失敗,可以利用這個特性來進行權(quán)限判斷。


客戶端發(fā)生遠程請求的同時,該線程會被掛起,知道得到響應或者被殺死。Binder得到客戶端的請求,通過onTransact()方法將data中的參數(shù)寫入到目標函數(shù),目標函數(shù)執(zhí)行完畢后將數(shù)據(jù)返回給客戶端。

AIDL就是通過Binder機制來進行進程間通信的。

AIDL創(chuàng)建:

客戶端:

綁定這個服務,將綁定成功后獲取到的IBider強轉(zhuǎn)成AIDL接口所屬的類型,就可以調(diào)用其方法了。

服務端:

首先創(chuàng)建一個服務用于監(jiān)聽客戶端的請求,然后創(chuàng)建一個AIDL文件,將暴露給客戶端的接口在AIDL文件中申明,然后服務端實現(xiàn)AIDL。

AIDL支持的數(shù)據(jù)類型:

基本數(shù)據(jù)類型(boolean,char,int,float,double,long,short,byte);

String和CharSequence;

List:只支持ArrayList并且里面元素都要被AIDL支持

Map:只支持HashMap;

Parcelable:所有被實現(xiàn)了Parcelable;

AIDL:所有AIDL文件。其中自定義的Parcelable對象和AIDL對象必須要顯示的improt進來,不管他們是否和AIDL文件處于相同的包內(nèi)。

如果AIDL文件中使用了Parelable對象,就必須在它相同的文件夾內(nèi)創(chuàng)建一個同這個對象的AIDL文件,申明這個是Parelable對象。如:


這里用到一個Book類,是可打包的,上述所說對于自定義的Parcelable需要顯示import,所以有 import com.example.myaidl.Book;然后在相同文件夾內(nèi)創(chuàng)建一個Book.aidl的文件:


在這個文件里面申明Book是可打包的即可:


AIDL回調(diào)管理:RemoteCallbackList是進程間通信過程中系統(tǒng)專門用于提供刪除Listener的接口。內(nèi)部有Map專門用來保存所有AIDL的回調(diào) key是IBinder類型,value是Callback類型如:

public class RemoteCallbackListArrayMapmCallbacks = new ArrayMap();

key是IBinder類型,valuew是Callback類型

IBinder key = listener.asBinder();

Callback value = new Callback(listener,cookie);

雖然所有的Binder對象在傳遞過程中會新生成不同的對象,但是底層的Binder對象是一個,這個底層對象會存儲在RemoteCallbackList中,在解除注冊時,我們只需要遍歷服務器所有的listener,找到對應的listener然后刪除就可以了

beginBroadcast()獲取有多少listener 必須要和finishBroadcast一起使用

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容