一.概念
IPC(Inter-Process Communication)意為進(jìn)程間通信或者跨進(jìn)程通信。
首選我們需要弄懂什么是進(jìn)程?和我們常提及的線程又是什么關(guān)系?
線程:CPU調(diào)度的最小單元,同時(shí)線程是一種有限的系統(tǒng)資源。
進(jìn)程:一般指一個(gè)執(zhí)行單元,在PC和移動(dòng)設(shè)備上指一個(gè)程序或一個(gè)應(yīng)用。
一個(gè)進(jìn)程可以包含多個(gè)線程,因此進(jìn)程與線程是包含與被包含的關(guān)系。
Android是基于Linux內(nèi)核的移動(dòng)操作系統(tǒng),它有著屬于自己的進(jìn)程間通信方式,而其中,最有特色的進(jìn)程間通信方式就是Binder了。
二.Android中的多進(jìn)程模式
1.開(kāi)啟多進(jìn)程
在Android(此處指一個(gè)應(yīng)用)中使用多進(jìn)程只有一種方法,就是給四大組件在AndroidManifest中指定android:process屬性,除此之外別無(wú)他法。
2.運(yùn)行機(jī)制
Android為每一個(gè)應(yīng)用分配了獨(dú)立的虛擬機(jī),或者說(shuō)為每個(gè)進(jìn)程都分配了獨(dú)立的虛擬機(jī),不同的虛擬機(jī)在內(nèi)存分配上有不同的地址空間,這就導(dǎo)致在不同的虛擬機(jī)中訪問(wèn)同一個(gè)類的對(duì)象會(huì)產(chǎn)生多份副本。
一般來(lái)說(shuō),使用多進(jìn)程會(huì)造成如下幾方面的問(wèn)題:
(1)靜態(tài)成員和單例模式完全失效
(2)線程同步機(jī)制完全失效
(3)SharedPreferences的可靠性下降
(4)Application會(huì)多次創(chuàng)建
運(yùn)行在不同進(jìn)程中的組件是屬于不同的虛擬機(jī)和Application的。
三.IPC介紹
1.Serialiazable接口
Serializable是Java所提供的的一個(gè)序列化接口,它是一個(gè)空接口,為對(duì)象提供標(biāo)準(zhǔn)的序列化和反序列化操作。
通常情況我們只需要讓一個(gè)類實(shí)現(xiàn)Serializable接口并聲明一個(gè)serialVersionUID就可以讓這個(gè)類的對(duì)象實(shí)現(xiàn)序列化。
public class User implements Serializable {
private static final long serialVersionUID = 123456789L;
public int id;
public String name;
......
}
其中serialVersionUID用來(lái)輔助序列化和反序列化過(guò)程,原則上序列化后的數(shù)據(jù)中的serialVersionUID只有和當(dāng)前類的serialVersionUID相同才能夠正常的被反序列化。
如果不指定serialVersionUID的話,系統(tǒng)會(huì)通過(guò)計(jì)算當(dāng)前類的hash值,自動(dòng)賦給
serialVersionUID。通過(guò)手動(dòng)指定serialVersionUID,可以很大程度上避免反序列化過(guò)程的失敗。
如:在版本升級(jí)后,可能刪除或添加了類中的成員變量,此時(shí)仍能成功的反序列化。
2.Parcelable接口
Parcelable也是一個(gè)接口,只要實(shí)現(xiàn)這個(gè)接口,一個(gè)類的對(duì)象就可以實(shí)現(xiàn)序列化并可以通過(guò)Intent和Binder傳遞。
public class User implements Parcelable {
public int id;
public String name;
public int age;
public User() {
}
//幾乎所有情況下都返回0,可以忽略該方法。
@Override
public int describeContents() {
return 0;
}
//實(shí)現(xiàn)序列化
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(this.id);
dest.writeString(this.name);
dest.writeInt(this.age);
}
//實(shí)現(xiàn)反序列化
protected User(Parcel in) {
this.id = in.readInt();
this.name = in.readString();
this.age = in.readInt();
}
public static final Parcelable.Creator<User> CREATOR = new Parcelable.Creator<User>() {
//調(diào)用反序列化方法
@Override
public User createFromParcel(Parcel source) {
return new User(source);
}
@Override
public User[] newArray(int size) {
return new User[size];
}
};
}
Android系統(tǒng)中Intent、Bundle、Bitmap等類已經(jīng)實(shí)現(xiàn)了Parcelable接口。
Serializable和Parcelable比較:
Serializable是Java中的序列化接口,其使用起來(lái)簡(jiǎn)單但是開(kāi)銷(xiāo)很大。
Parcelable是Android中的序列化方式,效率更高,缺點(diǎn)是使用較為麻煩。
此外,Parcelable主要用在內(nèi)存序列化上;通過(guò)序列化實(shí)現(xiàn)存儲(chǔ)和網(wǎng)絡(luò)傳輸還是建議用Serializable。
3.Binder
Binder是Android中的一個(gè)類,它實(shí)現(xiàn)了IBinder接口。
- 從IPC的角度來(lái)說(shuō),Binder是Android中的一種跨進(jìn)程通信方式。
- 從Android Framework角度來(lái)說(shuō),Binder是ServiceManager連接各種-Manager(ActivityManager、WindowManager等等)和相應(yīng)ManagerService的橋梁。
- 從Android應(yīng)用層來(lái)說(shuō),Binder是客戶端和服務(wù)端進(jìn)行通信的媒介,如Activity綁定Service。
Binder運(yùn)行機(jī)制:
服務(wù)端中的Service給與其綁定的客戶端提供Binder對(duì)象,客戶端通過(guò)AIDL接口中的asInterface()將這個(gè)Binder對(duì)象轉(zhuǎn)換為代理Proxy,并通過(guò)它發(fā)起RPC請(qǐng)求??蛻舳税l(fā)起請(qǐng)求時(shí)會(huì)掛起當(dāng)前線程,并將參數(shù)寫(xiě)入data然后調(diào)用transact(),RPC請(qǐng)求會(huì)通過(guò)系統(tǒng)底層封裝后由服務(wù)端的onTransact()處理,并將結(jié)果寫(xiě)入reply,最后返回調(diào)用結(jié)果并喚醒客戶端線程。

四.Android中的IPC

AIDL文件的本質(zhì)是系統(tǒng)為我們提供了一種快速實(shí)現(xiàn)Binder的工具,僅此而已。