Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
イベントをどう管理するか
Search
mikan
December 06, 2024
Technology
420
3
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
イベントをどう管理するか
【祝!50回】Shibuya.apk #50
https://shibuya-apk.connpass.com/event/336398/
mikan
December 06, 2024
More Decks by mikan
See All by mikan
Navigation3でやりとりした画面引数をSavedStateHandleから引き出せない理由
mikanichinose
0
31
Lazy APIを使ってGradleビルド速度を改善する
mikanichinose
1
92
Navigation3でViewModelにデータを渡す方法
mikanichinose
0
740
「脳に収まるコードの書き方」を読んで学んだこと
mikanichinose
1
240
RepositoryのSSoT化
mikanichinose
0
100
Kotlin Multiplatform 始めました
mikanichinose
1
170
Web APIをなぜつくるのか
mikanichinose
0
4.3k
ライブラリでしかお目にかかれない珍しい実装
mikanichinose
2
520
Strong Skipping Mode によってrecompositionはどう変わったのか
mikanichinose
0
420
Other Decks in Technology
See All in Technology
新機種発売前に見直そう!端末移行で再ログインが要るアプリ・要らないアプリは何が違うのか 〜シームレスに再開できる設計と実装〜
zozotech
PRO
0
220
Deployment の 先にある AI Agent 基盤 - kagent vNext、Agent Substrate、Hermes から読み解く Agent Runtime の現在地 / k8s-matsuri-2-ai-agent-platform-amsy810
masayaaoyama
4
670
サーバーレスをどこまで使う? WebRTC対戦ゲームで選んだVPSとの共存設計
kaidouji85
0
180
人間はどの意思決定を手放せるのか
kawasima
15
7.5k
LLMに渡さなかった仕事
nanaism
0
1.1k
Genieを崇めよ
kameitomohiro
0
170
Claude in Chrome 入門 / Introduction to Claude in Chrome
cielo1985
0
870
2026_devsumi_ozono.pdf
o3
3
530
山手線を徒歩で一周してわかった、 位置情報アプリは「足」が最強のデバッガー
hinakko
0
170
データ_AIの事業の勝敗をわけるもの
nek0128
1
460
アクセスキーこわい やめかたと漏らさない工夫
sassssan68
1
490
おい、エージェントを使って終わらせろ
nwiizo
2
750
Featured
See All Featured
AI: The stuff that nobody shows you
jnunemaker
PRO
10
1k
Pawsitive SEO: Lessons from My Dog (and Many Mistakes) on Thriving as a Consultant in the Age of AI
davidcarrasco
0
240
More Than Pixels: Becoming A User Experience Designer
marktimemedia
3
530
[SF Ruby Conf 2025] Rails X
palkan
3
1.4k
How STYLIGHT went responsive
nonsquared
100
6.3k
CSS Pre-Processors: Stylus, Less & Sass
bermonpainter
360
30k
A brief & incomplete history of UX Design for the World Wide Web: 1989–2019
jct
2
510
HTML-Aware ERB: The Path to Reactive Rendering @ RubyCon 2026, Rimini, Italy
marcoroth
5
690
Amusing Abliteration
ianozsvald
1
310
<Decoding/> the Language of Devs - We Love SEO 2024
nikkihalliwell
1
330
The Spectacular Lies of Maps
axbom
PRO
1
1k
Noah Learner - AI + Me: how we built a GSC Bulk Export data pipeline
techseoconnect
PRO
0
430
Transcript
イベントをどう管理するか Shibuya.apk #50 mikan(一瀬喜弘)
自己紹介 object Mikan { val name = 一瀬喜弘 val from
= 長崎 val company = カラビナテクノロジー株式会社 val work = Engineer.Android val volunteer = DroidKaigi val hobby = listOf( "漫画", "アニメ", "ゲーム", "折り紙", "OSS開発・コントリビュート", ) }
今日お話しする内容
Channel vs. SharedFlow vs. StateFlow エラーや 通信結果などの イベントを どこで 管理するのか
結論 エラーや 通信結果などの イベントを どこで 管理すべきか?
それぞれの メリデメを 把握したうえで 適当な ものを 選んでください
どれを 使うかは 所詮手段でしかないです 取り扱おうと している イベントの 重要度だったり、 どう ハンドリングされるかを きちんと
把握しないと 適切な ホルダーは 選べません
これから メリデメを 紹介するので、 適した 手段を 検討できるようになって もらえれば 幸いです
イベントとは
イベントとは ユーザー操作によってUI側から発生し、ViewModelに 伝達したい情報
None
けど ViewModelから UIに イベントを 送信したい ときも ありますよね
ex. 1. 通信が完了したら画面遷移する 2. 通信が失敗したらエラーダイアログを表示する 3. SharedPreferencesからデータを削除したらトーストを表示す る
None
ViewModelから UIに イベントを 伝達する ためにはなにかしら データホルダーが 必要に なる
Channel? SharedFlow? StateFlow? 戦争が始まる
それぞれについて実装方法をみ ていきます
Channel データの持ち方 イベントの発火 // ViewModel private val _message = Channel<String>()
val message = _message.receiveAsFlow() viewModelScope.launch { _message.send("message...") }
Channel イベントの消費 // Fragment viewLifecycleOwner.lifecycleScope.launch { viewLifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED) { viewModel.message.collect {
showSnackBar(it) } } }
Channel イベントの消費 // Compose val lifecycle = LocalLifecycleOwner.current.lifecycle LaunchedEffect(Unit) {
lifecycle.repeatOnLifecycle(Lifecycle.State.STARTED) { viewModel.message.collect { showSnackBar(it) } } }
Channel メリット collectorがいない間に発生したイベントをバッファリングできる(demo) デメリット イベントの 消費中に coroutine が キャンセルされたら どうしますか?
(demo)
Channel メリット collectorがいない間に発生したイベントをバッファリングできる(demo) デメリット イベントの 消費中に coroutine が キャンセルされたら どうしますか?
(demo) → バッファリングの挙動とバックグラウンド時のキャンセルが絡み合うとイベン トハンドリングの振る舞いがどんどん予測困難になる
SharedFlow データの持ち方 イベントの発火 // ViewModel private val _message = MutableSharedFlow<String>()
val message = _message.asSharedFlow() viewModelScope.launch { _message.emit("message...") }
SharedFlow イベントの消費 Channelのときと同じ // Fragment viewLifecycleOwner.lifecycleScope.launch { viewLifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED) { viewModel.message.collect
{ showSnackBar(it) } } }
SharedFlow イベントの消費 Channelのときと同じ // Compose val lifecycle = LocalLifecycleOwner.current.lifecycle LaunchedEffect(Unit)
{ lifecycle.repeatOnLifecycle(Lifecycle.State.STARTED) { viewModel.message.collect { showSnackBar(it) } } }
SharedFlow メリット デメリットに目を瞑れば、シンプルにイベントを実装できる デメリット collectorがいないとイベントは垂れ流されてロストする(demo) ex. 構成変更が発生するとUIが再構成されるので一瞬collectorがいなくなっ て、その間に発生したイベントはロストする イベントを発火するときに、subscriptionCountが1以上になっていること をチェックすることで回避可能だが。
。 replayCacheをいくらか設けて回避するという手もある
SharedFlow メリットともデメリットとも取れる collectorが複数いた場合に、1つのイベントが同時に複数回消費されることに なる(demo) ハンドリングが同じ場合は期待しない挙動になる可能性がある ハンドリングが異なる場合は有用な可能性がある このことを考慮して設計してあるならヨシ → Channelだと複数のcollectorに同じ情報を伝達できない
StateFlow データの持ち方 イベントの発火 // ViewModel // 初期値が必要だがイベントに初期値などないのでnullで表現する private val _message
= MutableStateFlow<String?>(null) val message = _message.asStateFlow() _message.value = "message..."
StateFlow // Fragment viewLifecycleOwner.lifecycleScope.launch { viewLifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED) { viewModel.message.collect { if
(it != null) { showSnackBar(it) // イベントをハンドリングしたあとは明示的に消費する viewModel.consumeMessage() } } } } // ViewModel fun consumeMessage() { _message.value = null }
StateFlow // Compose val message by viewModel.message.collectAsStateWithLifecycle() LaunchedEffect(message) { message?.let
{ onMessageReceive(it) viewModel.consumeMessage() } }
StateFlow メリット イベント処理中にcollectorがキャンセルされてたとしても、復帰後に最新のイ ベントは残っているので再ハンドリング可能 デメリット イベントの消費をプログラミングしないといけない 明示的にイベントを消し込み イベントを消費したとは? 論理的には消費したが、物理的に消費してない状態が成立する(demo)
まとめ Channel ⭕ トーストにメッセージを表示するなどの単純なイベントに向いている ⭕ collect前にイベントが発火する可能性がある場合に向いている ❌ イベントが消失する可能性があるので、重要なイベントには向いてない SharedFlow ⭕
トーストにメッセージを表示するなどの単純なイベントに向いている ⭕ バッファリングとか考えなくてよいのでシンプル ❌ イベントが消失する可能性があるので、重要なイベントには向いてない StateFlow ❌ 単純なイベントについては過度 ⭕ イベントの処理を保証しないといけない場合は向いている ⭕ 重要なイベントに向いている
ご清聴ありがとうございました