首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 程式設計入門

Android Parcelable 實現詳解:writeToParcel、CREATOR、高效 IPC 傳遞

     編輯:Java 程式設計入門

為何選 Parcelable?

Android IPC (Intent、Binder、AIDL) 僅支援基本類型、`String`、`Bundle`、實現 `Parcelable` 的對象。`Parcelable` 比 `Serializable` 快 10 倍+ (原生 C++ 實現、無反射)。

實現三要素

  1. writeToParcel(Parcel dest, int flags):序列化欄位順序寫入。
  2. describeContents():通常返回 0;含 `FileDescriptor` 時返回 `CONTENTS_FILE_DESCRIPTOR` (1)。
  3. static final Creator CREATOR:反序列化工廠,含 `createFromParcel`、`newArray`。

標準範本 (Kotlin 風格 Java)

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...
}

Parcel 讀寫順序鐵律

寫入順序 == 讀取順序。任何欄位增減/調序必須同步修改兩端,否則數據錯位導致 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)`,讀取時判斷
版本演進新增欄位寫在最後,舊版讀取會忽略 (需處理默認值)

常見坑點

  1. 忘記 `CREATOR` 靜態常量名:必須大寫 `CREATOR`,系統通過反射查找。
  2. `writeMap` 需 API 18+:低版本手寫 `dest.writeInt(map.size())` 迴圈寫 key/value。
  3. 內部類非 static:導致序列化外部類引用,記憶體洩漏。`CREATOR` 必須 `static`。
  4. 大對象拆分:超大 `Parcel` (>1MB) 會拋 `TransactionTooLargeException`,拆分傳遞或改用共享內存/文件。

Kotlin 簡化寫法

@Parcelize
data class Person(
    val name: String,
    val age: Int,
    val metadata: Map = emptyMap()
) : Parcelable

編譯器自動生成 `writeToParcel`、`CREATOR` 等樣板代碼。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved