@Parcelize は、Android × Kotlin 開発において Parcelable 実装を現実的なコストで扱うための必須機能です。
一方で、使い方を誤ると TransactionTooLargeException や設計崩壊の原因にもなります。
本記事では、
- Parcelizeの正確な役割
- Parcelableとの関係
- 現行API(Android 13 / API 33以降)を踏まえた正しい使い方
- 実務で事故らない設計指針
までを断定しすぎない・古くならない表現で整理します。
@Parcelizeとは何か
@Parcelize は、Kotlinコンパイラによって Parcelable 実装を自動生成する仕組みです。
本来、Parcelable を手書きすると以下が必要になります。
writeToParcel()describeContents()CREATORの実装- 読み書き順序の厳密管理
@Parcelize を使うと、これらを 宣言的に省略できます。
@Parcelize
data class User(
val id: Int,
val name: String
) : Parcelable
実装量を減らしつつ、Androidに最適化された高速なデータ受け渡しを実現できます。
ParcelableがAndroidで使われる理由
Androidでは、以下のような場面でオブジェクトの受け渡しが頻発します。
- Activity ↔ Activity
- Fragment ↔ Fragment
- Service ↔ Activity
- Intent / Bundle 経由の状態共有
この用途のために用意されているのが Parcelable です。
Serializableとの比較(実務視点)
| 観点 | Parcelable | Serializable |
|---|---|---|
| Android最適化 | ◎ | △ |
| 実行速度 | 高速 | 遅め |
| 実装コスト | 高い(通常) | 低い |
| @Parcelize使用時 | 低い | ― |
| 実務での推奨 | 基本はこちら | 例外的 |
SerializableはJava標準で手軽ですが、AndroidではParcelableが基本方針と考えるのが安全です。
Parcelizeを使うための設定
Gradle設定(必須)
plugins {
id("kotlin-parcelize")
}
kotlin-android-extensionsは 非推奨- Kotlin DSLの場合は
kotlin("parcelize")でも可
Intent / Bundleでの受け渡し(現行API準拠)
送る側
intent.putExtra("user", user)
受け取る側(API 33以降 推奨)
val user = intent.getParcelableExtra("user", User::class.java)
Fragmentの場合:
val user = arguments?.getParcelable("user", User::class.java)
※ 古い getParcelableExtra<T>(key) 形式はAPI 33以降では 非推奨(deprecated)扱いになるため注意が必要です。
Parcelizeで扱える型の考え方
Parcelizeは「型名」ではなく、Parcelに安全に書き込めるかどうかで可否が決まります。
問題なく使えるもの
- プリミティブ型(Int, Long, Boolean 等)
- String
- Enum
- Parcelableを実装したクラス
コレクション
List<T>
ArrayList<T>
※ T が Parcelable / プリミティブ等である必要あり
Mapについての注意
Map<String, T>
- 動作するケースはある
- しかし 型消去・可読性・保守性の観点でハマりやすい
- 実務では DTO に分解する方が安全
Nullable・デフォルト値
@Parcelize
data class Profile(
val name: String?,
val age: Int = 0
) : Parcelable
- Nullable → 問題なし
- デフォルト値 → 問題なし
enum / sealed class の扱い
enum
enum class Status { ACTIVE, INACTIVE }
問題なく Parcelize 可能です。
sealed class(重要)
@Parcelize
sealed class UiState : Parcelable {
@Parcelize
data class Success(val data: String) : UiState()
@Parcelize
data class Error(val message: String) : UiState()
}
- sealed class本体 + 各サブクラスに
@Parcelizeが必要 object型のサブクラスも同様
Parcelizeの仕組みとパフォーマンス
- Parcelizeは コンパイル時コード生成
- Serializableのようなリフレクションは使用しない
- データを順序固定のバイナリ形式で書き込む
そのため、一般に Parcelable + Parcelize の方が高速です。
(※ 実際の速度差はデータ量・端末条件に依存)
よくある落とし穴
巨大データを渡す
- Intent / Bundle 経由のデータは
Binderトランザクション制限によりTransactionTooLargeExceptionが発生することがあります - 実務上は「1MB前後で危険」と考えるのが一般的
✅ 対策
- IDやキーのみ渡す
- 実データは Repository / DB / キャッシュ経由で取得
Context / View を含める
val context: Context // ❌
- ライフサイクル問題
- 設計上もNG
Bitmapについて
Bitmapは Parcelable を実装している- 技術的には渡せる
- しかしサイズが大きくなりやすく、例外の原因になりがち
実務では URI / ファイルパス / キャッシュキーを渡すのが基本
@IgnoredOnParcel
@IgnoredOnParcel
val tempCache: String? = null
- Parcel化対象から除外できる
- 一時データ・計算結果向け
ただし、そもそも渡すモデルに含めない設計の方が健全なケースも多いです。
Serializableとの付き合い方(現実解)
- Androidでは 基本はParcelable
- Serializableは以下のような場合に限定して使われることがある
- 既存資産との互換
- 一時的な実装
- 非Android層との共通モデル
「Parcelize一択」と言い切るより、「原則Parcelable、例外的にSerializable」が正確です。
実務ベストプラクティスまとめ
- 画面遷移専用のDTOに Parcelize を使う
- DB Entity / Domain Model を直接 Parcelable にしない
- 大きなデータは渡さない
- UI State(sealed class)との相性は良い
- API 33以降の取得方法に注意
まとめ
@Parcelize は、Parcelableを「使えるもの」に変えた重要機能です。
ただし 便利さに任せて何でも詰め込むと事故るのも事実。
- 軽量
- 明確な責務
- 画面遷移専用
この3点を守れば、Parcelizeは Android開発における最強クラスの武器になります。
以上、KotlinのParcelizeについてでした。
最後までお読みいただき、ありがとうございました。










