Android IPC (Intent、Binder、AIDL) 僅支援基本類型、`String`、`Bundle`、實現 `Parcelable` 的對象。`Parcelable` 比 `Serializable` 快 10 倍+ (原生 C++ 實現、無反射)。
writeToParcel(Parcel dest, int flags):序列化欄位順序寫入。describeContents():通常返回 0;含 `FileDescriptor` 時返回 `CONTENTS_FILE_DESCRIPTOR` (1)。static final Creator CREATOR :反序列化工廠,含 `createFromParcel`、`newArray`。public class Person implements Parcelable {
private String name;
private int age;
private HashMap metadata; // 可序列化 Map
// 建構子
public Person(String name, int age) { this.name = name; this.age = age; }
// 1. 寫入
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(name);
dest.writeInt(age);
dest.writeMap(metadata); // 需 API 18+ 或自寫 key-value 迴圈
}
// 2. 內容描述
@Override
public int describeContents() { return 0; }
// 3. CREATOR
public static final Creator CREATOR = new Creator() {
@Override
public Person createFromParcel(Parcel in) {
return new Person(in); // 委託給讀取建構子
}
@Override
public Person[] newArray(int size) { return new Person[size]; }
};
// 讀取建構子 (私有/包可見)
private Person(Parcel in) {
name = in.readString();
age = in.readInt();
metadata = in.readHashMap(HashMap.class.getClassLoader());
}
// Getter/Setter...
}
寫入順序 == 讀取順序。任何欄位增減/調序必須同步修改兩端,否則數據錯位導致 Crash 或靜默錯誤。
| 場景 | 技巧 |
|---|---|
| List<Parcelable> | `dest.writeTypedList(list)` / `in.createTypedArrayList(Creator)` |
| SparseArray/ArrayMap | `dest.writeSparseArray()` / `in.readSparseArray()` (效率優於 HashMap) |
| Bitmap/Drawable | `dest.writeParcelable(bitmap, flags)` / `in.readParcelable()` |
| 可選欄位 | 寫入前先 `dest.writeByte(hasField ? 1 : 0)`,讀取時判斷 |
| 版本演進 | 新增欄位寫在最後,舊版讀取會忽略 (需處理默認值) |
@Parcelize
data class Person(
val name: String,
val age: Int,
val metadata: Map = emptyMap()
) : Parcelable
編譯器自動生成 `writeToParcel`、`CREATOR` 等樣板代碼。