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
イベントをどう管理するか
Search
mikan
December 06, 2024
Technology
3
330
イベントをどう管理するか
【祝!50回】Shibuya.apk #50
https://shibuya-apk.connpass.com/event/336398/
mikan
December 06, 2024
Tweet
Share
More Decks by mikan
See All by mikan
「脳に収まるコードの書き方」を読んで学んだこと
mikanichinose
1
100
RepositoryのSSoT化
mikanichinose
0
34
Kotlin Multiplatform 始めました
mikanichinose
1
120
Web APIをなぜつくるのか
mikanichinose
0
2.1k
ライブラリでしかお目にかかれない珍しい実装
mikanichinose
2
420
Strong Skipping Mode によってrecompositionはどう変わったのか
mikanichinose
0
280
Modeling UiEvent
mikanichinose
0
65
UIの構成要素に関する考察
mikanichinose
0
63
再考: 監視可能オブジェクト
mikanichinose
0
78
Other Decks in Technology
See All in Technology
SONiCにて使用されているSAIの実際
sonic
0
290
Why every SwiftUI developer should care about the Environment - iOSKonf25
peterfriese
0
160
生成AI時代における人間の情熱とプロダクト志向 / 20250517 Takuya Oikawa
shift_evolve
2
150
技術選定を突き詰める 懇親会LT
okaru
2
1.3k
20 Years of Domain-Driven Design: What I’ve Learned About DDD
ewolff
1
410
テストコードにはテストの意図を込めよう(2025年版) #retechtalk / Put the intent of the test 2025
nihonbuson
PRO
11
2.2k
LLMの開発と社会実装の今と未来 / AI Builders' Community (ABC) vol.2
pfn
PRO
3
240
NAB Show 2025 動画技術関連レポート / NAB Show 2025 Report
cyberagentdevelopers
PRO
0
130
技術選定の審美眼(2025年版) / Understanding the Spiral of Technologies 2025 edition
twada
PRO
72
20k
Microsoft Fabric のライセンスについて
ryomaru0825
2
3.5k
WindowsでGenesisに挑戦した話
natsutan
0
120
encoding/json v2を予習しよう!
yuyu_hf
PRO
1
220
Featured
See All Featured
Optimising Largest Contentful Paint
csswizardry
37
3.2k
The Power of CSS Pseudo Elements
geoffreycrofte
75
5.8k
GitHub's CSS Performance
jonrohan
1031
460k
Building Flexible Design Systems
yeseniaperezcruz
329
39k
Art, The Web, and Tiny UX
lynnandtonic
298
20k
Performance Is Good for Brains [We Love Speed 2024]
tammyeverts
10
810
Raft: Consensus for Rubyists
vanstee
137
6.9k
ピンチをチャンスに:未来をつくるプロダクトロードマップ #pmconf2020
aki_iinuma
122
52k
Documentation Writing (for coders)
carmenintech
71
4.8k
Creating an realtime collaboration tool: Agile Flush - .NET Oxford
marcduiker
30
2k
Code Review Best Practice
trishagee
68
18k
RailsConf & Balkan Ruby 2019: The Past, Present, and Future of Rails at GitHub
eileencodes
137
33k
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 ❌ 単純なイベントについては過度 ⭕ イベントの処理を保証しないといけない場合は向いている ⭕ 重要なイベントに向いている
ご清聴ありがとうございました