### 三、IPC基礎概念介紹
當我們需要通過Intent和Binder傳輸數據時就需要使用Parcelable或者Serializeble。Serializable和Parcelable接口可以完成對象的序列化過程。還有時候我們需要把對象持久化到存儲 設備上或者通過網絡傳輸給其他客戶端,這個時候也需要Serializable來完成對象的持久化。
#### 1、Serializable接口
(1)Serializable是Java所提供的一個序列化接口,它是一個空接口,為對象提供標準的序列化和反序列化操作。使用Serializable來實現序列化非常簡單,只需要在類的聲明中指定一個類似下面的標識即可自動實現默認的序列化過程。
~~~
private static final long serialVersionUID = 8723148825838841922L;
public class User implements Serializable{
private static final long serialVersionUID = 8723148825838841922L;
public int userId;
public String userName;
public boolean isMale;
}
~~~
(2)只需要采用ObjectOutputStream和ObjectInputStream即可輕松實現對象的序列化和反序列化過程:
~~~
// 序列化過程:
User user = new User(0,"jake",true);
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("cache.txt"));
out.writeObject(user);
out.close();
// 反序列化過程:
ObjectInputStream in = new ObjectInputStream(new FileInputStream("cache.txt"));
User newUser = (User)in.readObject();
in.close();
~~~
**注意點一**:序列化和反序列化的對象并不是同一個對象!
(3)一般來說,我們應該手動指定serialVersionUID的值,比如1L,也可以讓Eclipse根據當前類的結構自動去生成它的hash值。當我們手動指定了它以后,就可以在很大程度上避免反序列化過程的失敗。
**注意點二**:靜態成員變量屬于類不屬于對象,所以不會參與序列化過程。
**注意點三**:用transient關鍵字標記的成員變量不參與序列化過程。
**注意點四**:通過重寫writeObject和readObject方法可以改變系統默認的序列化過程。
#### 2、Parcelable接口
在Android 中也提供了新的序列化方式,那就是Parcelable 接口,使用Parcelable 來實現對象的序列號,其過程要稍微復雜一些。
(1)Parcelable也是一個接口,只要實現這個接口,一個類的對象就可以實現序列化并可以通過Intent和Binder傳遞。
~~~
public class User implements Parcelable {
public int userId;
public String userName;
public boolean isMale;
public Book book;
public User(int userId, String userName, boolean isMale) {
this.userId = userId;
this.userName = userName;
this.isMale = isMale;
}
/*
* 內容描述功能幾乎都是直接返回0的。
* */
public int describeContents() {
return 0;
}
/*
* 序列化由writeToParcel方法來完成,最終是通過Parcel中一系列write方法來完成的。
* 其中flags標識有兩種值:0和1(PARCELABLE_WRITE_RETURN_VALUE)。
* 為1時標識當前對象需要作為返回值返回,不能立即釋放資源,
* 幾乎所有情況都為0。
* */
public void writeToParcel(Parcel out, int flags) {
out.writeInt(userId);
out.writeString(userName);
out.writeInt(isMale? 1:0);
out.writeParcelable(book, 0);
}
/*
* 反序列化功能是由CREATOR來完成,其內部標明了如何創建序列化對象和數組,
* 并通過Parcel的一些了read方法來完成反序列化過程。
* */
public static final Parcelable.Creator<User> CREATOR = new Parcelable.Creator<User>() {
// 從序列化后的對象中創建原始對象。
public User createFromParcel(Parcel in) {
return new User(in);
}
// 創建指定長度的原始對象數組
public User[] newArray(int size) {
return new User[size];
}
};
/*
* Parcel內部包裝了可序列化的數據,可以在Binder中自由傳輸。
* 從序列化后的對象中創建原始對象。
* */
private User(Parcel in) {
userId = in.readInt();
userName = in.readString();
isMale = in.readInt() == 1;
/*
* 由于book是另一個可序列化對象,所以它的反序列化過程需要傳遞當前線程的上下文類加載器,
* 否則會報無法找到類的錯誤。
* */
book = in.readParcelable(Thread.currentThread().getContextClassLoader());
}
}
~~~
Parcelable的方法說明如下表

(2)系統已經為我們提供了許多實現了Parcelable接口的類,它們都是可以直接序列化的,比如Intent、Bundle、Bitmap等,同時List和Map也可以序列化,前提是它們里面的每個元素都是可序列化的。
** Parcelable接口和Serializable接口的比較**
(1)Serializable用起來簡單,但開銷很大,序列化和反序列化過程都需要大量的I/O操作。
(2)Parcelable是Android中的序列化方式,更適合在Android平臺上使用,用起來比較麻煩,但效率很高,首選。主要用在內存序列化上。通過Parcelable 將對象序列化到存儲設備中或者將對象序列化后通過網絡傳輸也都是可以的,但是這個過程會稍顯復雜,因此在這兩種情況下建議大家使用Serializable。
#### 3、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開發中,Binder主要用在Service中,包括AIDL和Messenger,其中普通Service中的Binder不涉及進程間通信。Messenger的核心其實是AIDL。這里選用aidl來分析Binder的工作機制。
- 前言
- 第一章Activity的生命周期和啟動模式
- 1.1 Activity生命周期全面分析
- 1.2 Activity的啟動模式
- 1.3 IntentFilter的匹配規則
- 第二章IPC
- 轉 chapter IPC
- 轉IPC1
- 轉IPC2
- Binder講解
- binder
- Messenger
- 一、Android IPC簡介
- 二、Android中的多進程模式
- 三、IPC基礎概念介紹
- 四、Android中的IPC方式
- 五、Binder連接池
- 第三章
- 第九章四大組件的工作過程
- 第十章
- 第13章 綜合技術
- 使用CrashHandler 來獲取應用的crash 信息
- 使用Multidex來解決方法數越界
- Android的動態加載技術