Android IPC簡介
IPC是Inter-Process Communication的縮寫,含義就是進程間通信或者跨進程通信,是指兩個進程之間進行數據交換的過程。那么什么是進程,什么是線程,進程和線程是兩個截然不同的概念。在操作系統中,線程是CPU調度的最小單元,同時線程是一種有限的系統資源。而進程指的一個執行單元,在PC和移動設備上指的是一個程序或者一個應用。一個進程可以包含多個線程,因此進程和線程是包含被包含的關系,最簡單情況下,一個進程可以只有一個線程,即主線程,在Android里面也叫UI線程,在UI線程里才能操作界面元素。
那么在Android中,有特色的進程間通信方式就是Binder了,通過Binder可以輕松實現進程間通信。除了Binder,Android還支持Socket,通過Socket也可以實現任意兩個終端之間的通信,當然一個設備上的兩個進程之間通過Socket通信自然也是可以的。
說到IPC的使用場景就必須提到多進程,只有面對多進程這種場景下,才需要考慮進程間通信。所有運行在不同進程中的四大組件,只要它們之間需要通過內存來共享數據,都會共享失敗,這也是多進程所帶來的主要影響。正常情況下,四大組件中間不可能不通過一些中間層來共享數據,那么通過簡單地指定進程名來開啟多進程都會無法正確運行。一般來說,使用多進程會造成如下幾方面的問題:
- 靜態成員和單例模式完全失效
- 線程同步機制完全失效
- SharedPreferences的可靠性下降
- Application會多次創建
為了解決這個問題,系統提供了很多跨進程通信方法,雖然說不能直接地共享內存,但是通過跨進程通信我們還是可以實現數據交互。實現跨進程通信的方式有很多,比如通過Intent來傳遞數據,共享文件SharedPreference,基於Binder的Messenger和AIDL以及Socket等。
IPC基礎概念介紹
Serializable接口
Serializable是Java提供的一個序列化接口,它是一個空接口,為對象標准的序列化和反序列化操作。使用Serializable來實現序列化相當簡單,一句話即可。
public class User implements Serializable {
private static final long seriaVersionUID = 519067123721295773L
}
Parcelable接口
Parcel內部包裝了可序列化的數據,可以在Binder中自由傳輸,在序列化過程中需要實現的功能有序列化、反序列化和內容描述序列化功能有writeToParcel
方法來完成,最終是通過Parcel中的一系列write
方法來完成的。用法如下:
public class MyParcelable implements Parcelable {
// You can include parcel data types
private int mData;
private String mName;
// We can also include child Parcelable objects. Assume MySubParcel is such a Parcelable:
private MySubParcelable mInfo;
// This is where you write the values you want to save to the `Parcel`.
// The `Parcel` class has methods defined to help you save all of your values.
// Note that there are only methods defined for simple values, lists, and other Parcelable objects.
// You may need to make several classes Parcelable to send the data you want.
@Override
public void writeToParcel(Parcel out, int flags) {
out.writeInt(mData);
out.writeString(mName);
out.writeParcelable(mInfo, flags);
}
// Using the `in` variable, we can retrieve the values that
// we originally wrote into the `Parcel`. This constructor is usually
// private so that only the `CREATOR` field can access.
private MyParcelable(Parcel in) {
mData = in.readInt();
mName = in.readString();
mInfo = in.readParcelable(MySubParcelable.class.getClassLoader());
}
public MyParcelable() {
// Normal actions performed by class, since this is still a normal object!
}
// In the vast majority of cases you can simply return 0 for this.
// There are cases where you need to use the constant `CONTENTS_FILE_DESCRIPTOR`
// But this is out of scope of this tutorial
@Override
public int describeContents() {
return 0;
}
// After implementing the `Parcelable` interface, we need to create the
// `Parcelable.Creator<MyParcelable> CREATOR` constant for our class;
// Notice how it has our class specified as its type.
public static final Parcelable.Creator<MyParcelable> CREATOR
= new Parcelable.Creator<MyParcelable>() {
// This simply calls our new constructor (typically private) and
// passes along the unmarshalled `Parcel`, and then returns the new object!
@Override
public MyParcelable createFromParcel(Parcel in) {
return new MyParcelable(in);
}
// We just need to copy this and change the type to match our class.
@Override
public MyParcelable[] newArray(int size) {
return new MyParcelable[size];
}
};
}
Serializable和Parcelable區別
Serializable是Java中的序列化接口,其使用起來簡單但是開銷很大,在序列化和反序列化過程中需要大量的I/O操作。而Parcelable是Android中的序列化方式,因此更適合用在Android平台上,它的缺點就是使用起來稍微麻煩點,但是它的效率很高。
Binder
直觀來說,Binder是Android中的一個類,它實現了IBinder接口。從IPC角度來說,Binder是Android中的一種跨進程通信方式,Binder還可以理解為一種虛擬的物理設備,它的設備驅動是/dev/binder,該通信方式在Linux中沒有。從Android Framework角度來說,Binder是ServiceManager連接各種Manager(ActivityManager、WindowManager等等)和相應ManagerService的橋梁。從Android應用層來說,Binder是客戶端和服務端進行通信的媒介,當bindService的時候,服務端會返回一個包含了服務端業務調用的Binder對象,通過Binder對象,客戶端就可以獲取服務端提供的服務或者數據,這里的服務包括普通服務和基於AIDL的服務。
Android中的IPC方式
使用Bundler
我們知道,四大組件中三大組件(activity、service、receiver)都是支持在Intent中傳遞Bundle數據的,由於Bundle實現了Parcelable接口,所以它可以方便地在不同的進程間傳輸。
使用文件共享
共享文件也是一種不錯的進程間通信方式,兩個進程間通過讀/寫同一個文件來交換數據,比如A進程把數據寫入文件,B進程通過讀取這個文件來獲取數據。
使用Messenger
Messenger可以翻譯為信使,顧名思義,通過它可以在不同進程中傳遞Message對象,在Message中放入我們需要傳遞的數據,就可以輕松地實現數據的進程間傳遞。Messenger是一種輕量級的IPC方案,它的底層實現是AIDL,實現Messenger有以下兩個步驟,分為服務端進程和客戶端進程。
使用AIDL
遠程服務跨進程通信的一種方式。
使用ContentProvider
ContentProvider是Android中提供的專門用於不同應用間進行數據共享的方式,它的底層實現同樣也是Binder。
使用Socket
Socket也稱為“套接字”,是網絡通信中的概念,它分為流式套接字和用戶數據套接字兩種,分別應於網絡的傳輸控制層中的TCP和UDP協議。
選用合適的IPC方式
閱讀擴展
源於對掌握的Android開發基礎點進行整理,羅列下已經總結的文章,從中可以看到技術積累的過程。
1,Android系統簡介
2,ProGuard代碼混淆
3,講講Handler+Looper+MessageQueue關系
4,Android圖片加載庫理解
5,談談Android運行時權限理解
6,EventBus初理解
7,Android 常見工具類
8,對於Fragment的一些理解
9,Android 四大組件之 " Activity "
10,Android 四大組件之" Service "
11,Android 四大組件之“ BroadcastReceiver "
12,Android 四大組件之" ContentProvider "
13,講講 Android 事件攔截機制
14,Android 動畫的理解
15,Android 生命周期和啟動模式
16,Android IPC 機制
17,View 的事件體系
18,View 的工作原理
19,理解 Window 和 WindowManager
20,Activity 啟動過程分析
21,Service 啟動過程分析
22,Android 性能優化
23,Android 消息機制
24,Android Bitmap相關
25,Android 線程和線程池
26,Android 中的 Drawable 和動畫
27,RecylerView 中的裝飾者模式
28,Android 觸摸事件機制
29,Android 事件機制應用
30,Cordova 框架的一些理解
31,有關 Android 插件化思考
32,開發人員必備技能——單元測試