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
CI/CD/IaC 久々に0から環境を作ったらこうなりました
kaz29
1
150
GeminiとNotebookLMによる金融実務の業務革新
abenben
0
210
Observability infrastructure behind the trillion-messages scale Kafka platform
lycorptech_jp
PRO
0
130
25分で解説する「最小権限の原則」を実現するための AWS「ポリシー」大全 / 20250625-aws-summit-aws-policy
opelab
9
990
より良いプロダクトの開発を目指して - 情報を中心としたプロダクト開発 #phpcon #phpcon2025
bengo4com
1
3.1k
あなたの声を届けよう! 女性エンジニア登壇の意義とアウトプット実践ガイド #wttjp / Call for Your Voice
kondoyuko
4
300
標準技術と独自システムで作る「つらくない」SaaS アカウント管理 / Effortless SaaS Account Management with Standard Technologies & Custom Systems
yuyatakeyama
3
1.2k
JSX - 歴史を振り返り、⾯⽩がって、エモくなろう
pal4de
4
1.1k
Node-REDのFunctionノードでMCPサーバーの実装を試してみた / Node-RED × MCP 勉強会 vol.1
you
PRO
0
110
強化されたAmazon Location Serviceによる新機能と開発者体験
dayjournal
2
190
変化する開発、進化する体系時代に適応するソフトウェアエンジニアの知識と考え方(JaSST'25 Kansai)
mizunori
0
180
2025/6/21 日本学術会議公開シンポジウム発表資料
keisuke198619
2
490
Featured
See All Featured
Imperfection Machines: The Place of Print at Facebook
scottboms
267
13k
Building Adaptive Systems
keathley
43
2.6k
GraphQLとの向き合い方2022年版
quramy
47
14k
Building Better People: How to give real-time feedback that sticks.
wjessup
367
19k
Visualization
eitanlees
146
16k
[RailsConf 2023] Rails as a piece of cake
palkan
55
5.6k
CSS Pre-Processors: Stylus, Less & Sass
bermonpainter
357
30k
The Straight Up "How To Draw Better" Workshop
denniskardys
233
140k
Building Flexible Design Systems
yeseniaperezcruz
328
39k
4 Signs Your Business is Dying
shpigford
184
22k
GraphQLの誤解/rethinking-graphql
sonatard
71
11k
BBQ
matthewcrist
89
9.7k
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