Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Serializable / Parcelableとの上手な付き合い方
Search
kobayashi_kento
April 24, 2025
Technology
0
47
Serializable / Parcelableとの上手な付き合い方
2025年4月24日(木)開催のpixiv App Nightで発表した資料です。
kobayashi_kento
April 24, 2025
Tweet
Share
More Decks by kobayashi_kento
See All by kobayashi_kento
Kotlinの好きなところ
kobaken0029
0
930
Compose駆動開発のためのマルチモジュール化
kobaken0029
0
210
DataStoreを導入してみた
kobaken0029
1
310
Epoxyを用いたレイアウト構築術
kobaken0029
1
230
Androidエンジニアが1週間でiOSアプリ開発を学び、1ヶ月で大規模アプリ開発にJOINした話
kobaken0029
0
3.2k
Modern REST Communicate for Android
kobaken0029
0
1.5k
AndroidでモダンREST通信してみたった
kobaken0029
0
250
Other Decks in Technology
See All in Technology
AWS Summit Japan 2025 Community Stage - App workflow automation by AWS Step Functions
matsuihidetoshi
1
160
Oracle Audit Vault and Database Firewall 20 概要
oracle4engineer
PRO
3
1.7k
OAuth/OpenID Connectで実現するMCPのセキュアなアクセス管理
kuralab
5
900
Witchcraft for Memory
pocke
1
140
Oracle Cloud Infrastructure:2025年6月度サービス・アップデート
oracle4engineer
PRO
2
150
[TechNight #90-1] 本当に使える?ZDMの新機能を実践検証してみた
oracle4engineer
PRO
3
140
Amplifyとゼロからはじめた AIコーディング 成果と展望
mkdev10
1
380
BigQuery Remote FunctionでLooker Studioをインタラクティブ化
cuebic9bic
2
240
20250625 Snowflake Summit 2025活用事例 レポート / Nowcast Snowflake Summit 2025 Case Study Report
kkuv
1
250
2年でここまで成長!AWSで育てたAI Slack botの軌跡
iwamot
PRO
4
550
Definition of Done
kawaguti
PRO
6
470
Amazon ECS & AWS Fargate 運用アーキテクチャ2025 / Amazon ECS and AWS Fargate Ops Architecture 2025
iselegant
16
4.9k
Featured
See All Featured
A better future with KSS
kneath
239
17k
Designing Experiences People Love
moore
142
24k
Site-Speed That Sticks
csswizardry
10
650
Fight the Zombie Pattern Library - RWD Summit 2016
marcelosomers
233
17k
Code Reviewing Like a Champion
maltzj
524
40k
[RailsConf 2023 Opening Keynote] The Magic of Rails
eileencodes
29
9.5k
Building Better People: How to give real-time feedback that sticks.
wjessup
367
19k
Building an army of robots
kneath
306
45k
Balancing Empowerment & Direction
lara
1
350
[RailsConf 2023] Rails as a piece of cake
palkan
55
5.6k
Automating Front-end Workflow
addyosmani
1370
200k
Design and Strategy: How to Deal with People Who Don’t "Get" Design
morganepeng
130
19k
Transcript
Serializable / Parcelableとの 上手な付き合い方 @kobaken
Index • Serializable / Parcelableとは • pixivコミックで問題になった事象 • なぜ発生してしまったのか •
今後の運用方針 • まとめ 2
Serializable / Parcelable 3
4 https://developer.android.com/develop/ui/views/touch-and-input/stylus-input/ink-api-state-preservation
5 https://developer.android.com/develop/ui/views/touch-and-input/stylus-input/ink-api-state-preservation
6 🤔💭
Serializable / Parcelableとは • オブジェクトを直列化するためのinterface ◦ オブジェクトをバイト列に変換(シリアライズ)、復元(デシリアライズ)する処理 • ActivityやFragment, Serviceなどのコンポーネント間のデータ受け渡し(画面遷移
など)や永続化などの際に利用されることが多い 7
Serializable 8 Java標準のシリアライズ機構 ※Kotlin Serializationの@Serializableではないです Pros • Serializableと追加するだけなので実装が容易 • Javaの実行環境であれば動作する
Cons • シリアライズ/デシリアライズの処理速度が 遅い • メモリ消費量が大きい import java.io.Serializable data class Hoge( val fuga: String, val piyo: Int, ) : Serializable
Parcelable 9 AndroidのParcel機構 メモリ上で効率的にデータをやり取りするために設 計されている Pros • シリアライズ/デシリアライズの処理速度が速い • メモリ効率が良い
Cons • 実装がやや複雑で面倒 • 永続化には向かない import android.os.Parcelable data class Hoge( val fuga: String, val piyo: Int, ) : Parcelable { constructor(parcel: Parcel): this( parcel.readString() ?: "", parcel.readInt(), ) override fun writeToParcel(dest: Parcel?, flags: Int) { if (dst != null) { dest.writeString(fuga) dest.writeInt(piyo) } } override fun describeContents() = 0 companion object CREATOR : Parcelable.Creator<Hoge> { override fun createFromParcel(parcel: Parcel) = Hoge(parcel) override fun newArray(size: Int): Array<Hoge?> = arrayOfNulls(size) } }
Parcelable 10 AndroidのParcel機構 メモリ上で効率的にデータをやり取りするために設 計されている Pros • シリアライズ/デシリアライズの処理速度が速い • メモリ効率が良い
Cons • 実装がやや複雑で面倒 • 永続化には向かない import android.os.Parcelable import kotlinx.parcelize.Parcelize @Parcelize data class Hoge( val fuga: String, val piyo: Int, ) : Parcelable kotlin-parcelize @Parcelizeで おk
問題になった事象 11
前提 • pixivコミック Androidアプリでは画面遷移をActivity.startActivityで行っている • マルチモジュール化を進行中 ◦ 大半の実装がappモジュール内にまとまったままになっている 12
問題になった事象 • 画面遷移時にBundleからデータを取得する箇所でクラッシュが発生💣💥 13
問題になった事象 • 画面遷移時にBundleからデータを取得する箇所でクラッシュが発生💣💥 解決策 • Serializableにロールバックした ◦ 早急な対応のため、手数が少なく、動作の実績がある元実装に戻した 14
なぜ発生したのか • 対応するclassをSerializable->Parcelableに置き換えていたが、Bundleから取り出 す処理をSerializable時代のままにしていた • pixivコミック Androidチームでは変更箇所の動作確認をリリース前に行なっている • 当時改修対象だった機能の動作も問題なかった ◦
影響範囲の調査不足(影響範囲が広い実装の変更だった) 15
今後の運用方針 16
今後の運用方針 • 新規実装ではParcelableを使用する ◦ @Parcelizeを活用する • 役割を明確にするため、画面遷移に利用するデータはドメインモデルとは別に定義 ◦ 便宜上、ナビゲーションモデルと呼ぶ ◦
ナビゲーションモデルはnavigationモジュールに配置する ◦ ナビゲーションモデル<-->ドメインモデルの変換ロジックもnavigationモジュールに配置する 17
Parcelableに変えていく理由 • IntentやBundleのListの扱いがSerializableよりParcelableが型安全 • Serializableよりパフォーマンス面に優れているParcelableを利用 18
Listの扱いが型安全 19 • Listの型を指定して型安全に取得可能 • Serializableの場合は自分でキャスト data class Hoge( val
fuga: String, val piyo: Int, ) : Parcelable // IntentからHogeのArrayListを取得 IntentCompat.getParcelableArrayListExtra( /* in = */ intent, /* key = */ “hoge”, /* clazz = */ Hoge::class.java ) // SerializableはList専用の口がないのでキャストする IntentCompat.getSerializableExtra( /* in = */ data, /* key = */ “hoge”, /* clazz = */ ArrayList::class.java ) as? ArrayList<Hoge>
Serializable vs Parcelable Serizliable • Java • 実装が楽 • 処理速度が遅め
• メモリ消費大 20 Parcelable • Android固有 • 実装が面倒(プラグインで自動生成が可能) • 処理速度が速め • メモリ消費小
Serializableと比較してParcelableがパフォーマンス優勢な理由 • リフレクションしていない ◦ writeToParcelで明示的に書き出す対象を指定するので解析の手間がなく、実行時の処理が速い • writeString, readString などの専用メソッドにより効率化 ◦
余計なGCのオーバーヘッドを削減 • Parcelの内部実装で最適化が行われている ◦ メモリマッピングなど • オブジェクトの循環参照を回避している ◦ 循環参照が発生する可能性がある場合、IDを利用して既にデシリアライズされたものを再利用したり、呼 び出された時に参照を解決したりして解決できる 21
モデルの相互変換 22 • それぞれのプロパティに1対1対応す るシンプルな変換 ◦ 遷移元->toNavigationModel ◦ 遷移先->toModel •
kotlin-fill-classというプラグインを 活用すると効率UP ◦ https://plugins.jetbrains.com/plugin/1094 2-kotlin-fill-class // core/data/model/~/Hoge.kt data class Hoge( val fuga: String, val piyo: Int, ) // core/navigation/~/model/Hoge.kt data class Hoge( val fuga: String, val piyo: Int, ) : Parcelable // core/navigation/~/model/converter/DoM2NaviM.kt fun Hoge.toNavigationModel() = hoge.sample.core.navigation.model.Hoge( fuga = fuga, piyo = piyo, ) // core/navigation/~/model/converter/NaviM2DoM.kt fun Hoge.toModel() = hoge.sample.core.data.model.Hoge( fuga = fuga, piyo = piyo, )
まとめ 23
まとめ • ActivityやFragment間のデータ受け渡しはSerializableよりParcelableが優秀 ◦ シリアライズの速度やメモリ効率もParcelableに軍配があがる ◦ ただし、永続化に使うのは避けること • @Parcelizeを活用すべし ◦
kotlin-parcelizeを導入しよう ◦ ボイラープレートを自動生成してくれて便利 • 役割ごとに型を分けて影響範囲を明確にする ◦ 今回は画面遷移時に引き渡されるパラメータとしてナビゲーションモデルを定義した ◦ ナビゲーションモデルはBundleに格納・取出することに集中する ◦ 遷移先でドメインモデルとして振る舞えるように相互変換を実装する 24
参考文献 • https://developer.android.com/kotlin/parcelize?hl=ja#skip_properties_from _serialization • https://developer.android.com/privacy-and-security/risks/unsafe-deserializ ation • https://outcomeschool.com/blog/parcelable-vs-serializable •
https://mixi-inc.github.io/AndroidTraining/fundamentals/2.07.serialize-and- collection-and-perpetuation.html#直列化 • Gemini Advanced 2.0 Flash 25