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
Navigation3でViewModelにデータを渡す方法
Search
mikan
June 24, 2025
Technology
770
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Navigation3でViewModelにデータを渡す方法
https://yumemi.connpass.com/event/357336/
mikan
June 24, 2025
More Decks by mikan
See All by mikan
形式手法を使って仕様をコーディングしよう
mikanichinose
0
140
Navigation3でやりとりした画面引数をSavedStateHandleから引き出せない理由
mikanichinose
0
35
Lazy APIを使ってGradleビルド速度を改善する
mikanichinose
1
92
「脳に収まるコードの書き方」を読んで学んだこと
mikanichinose
1
240
RepositoryのSSoT化
mikanichinose
0
100
Kotlin Multiplatform 始めました
mikanichinose
1
170
Web APIをなぜつくるのか
mikanichinose
0
4.3k
イベントをどう管理するか
mikanichinose
3
420
ライブラリでしかお目にかかれない珍しい実装
mikanichinose
2
520
Other Decks in Technology
See All in Technology
生成AIを使って「人が」考える技術 ― AI時代の人機共想と実践ノウハウ|UNITT AC2026
ishiirikie
0
420
Argo CDとAtlantisで実現するインフラ管理のセルフサービス化──小規模SREチームで支えるプラットフォーム
cassius7
0
250
顧客の成果創出とプロダクトの成長を 両立するためのFDE
sansantech
PRO
0
460
個別開発で終わらせない。 現場の課題をプロダクトの強さに変える StockmarkのFDE
ktkrhr
0
380
Azure Copilot Resiliency Agentをいろいろ試してみる
tomokusaba
0
140
AgentCore Runtime上にAgentic Coding基盤を構築・展開する際の設計ポイントと限界点 / Design considerations and limitations when building an agentic coding platform on AgentCore Runtime
har1101
7
830
PQC移行の今 -- IETF からみた現在地
satokan
4
640
GitHub Agentic Workflows を触ってみる
htkym
2
870
音声コミュニティを守るAI監視基盤_ 90%以上の入力削減を支えたServerless設計と運用判断
shuheioka123
0
120
AIに賢く動いてもらうためのコンテキスト〜Snowflake女子会 vol.8
snowwmn0824
0
200
MCPゲートウェイを作って運用してわかったこと — Agent時代の権限管理の現在地
mtpooh
4
400
手を動かして実感する、Kiro が変える開発体験
inariku
0
420
Featured
See All Featured
Public Speaking Without Barfing On Your Shoes - THAT 2023
reverentgeek
1
570
BBQ
matthewcrist
89
10k
A Guide to Academic Writing Using Generative AI - A Workshop
ks91
PRO
1
500
Stop Working from a Prison Cell
hatefulcrawdad
274
21k
Navigating the moral maze — ethical principles for Al-driven product design
skipperchong
2
590
Navigating the Design Leadership Dip - Product Design Week Design Leaders+ Conference 2024
apolaine
2
450
Efficient Content Optimization with Google Search Console & Apps Script
katarinadahlin
PRO
1
890
Redefining SEO in the New Era of Traffic Generation
szymonslowik
1
450
The Language of Interfaces
destraynor
162
27k
Fashionably flexible responsive web design (full day workshop)
malarkey
409
67k
Lessons Learnt from Crawling 1000+ Websites
charlesmeaden
PRO
1
1.6k
ラッコキーワード サービス紹介資料
rakko
1
5.1M
Transcript
Navigation3 で ViewModel に データを 渡す方 法 モバチキ#8 mikan( 一瀬喜弘)
自己紹介 object Mikan { val name = "一瀬喜弘" val company
= "karabiner.tech" val occupation = Engineer.Android var work = "OisixのAndroidアプリ開発" val favoriteCharacter.GQuuuuuuX = "コモリ・コーハート" }
🙇♂️🙇♂️ 注意 🙇♂️🙇♂️ まだ Alpha 版でしかない Navigation3 に ついて 基本的な
ことを 大して 語らずに いきなりAdvanced な 内容を 話します
Navigation3 でましたね
Navigation3 でましたね
ちなみに Oisix に Navigation なんて 贅沢な ものは ありません FragmentManager でがんばってます💪
Navigation3 で 使われる コンポーネントと Navigation Component との 対比
Navigation3 で使われるコンポーネント BackStack: 画面遷移の履歴 実体は SnapshotStateList<Any> NavDisplay: BackStack を監視して、現在のキーに相当するUI を表示する
EntryProvider: キーをNavEntry に変換する関数 (key) -> NavEntry NavEntry: キーとコンテンツを結び付ける metadata: アニメーションの制御とか NavKey: BackStack をrememberSaveable したいときに必要になる (SceneStrategy: adaptive layout 対応)
Navigation Component との対比 Navigation Component Navigation3 NavController SnapshotStateList BackStackEntry NavEntry
NavHost NavDisplay NagGraph EntryProvider
Navigation とViewModel
Navigation とViewModel Navigation とViewModel を組み合わせるときに必要になる考慮 ライフサイクル管理 遷移先へのデータ授受
Navigation とViewModel Navigation とViewModel を組み合わせるときに必要になる考慮 ライフサイクル管理 ViewModel のライフサイクルをBackStack に合わせる BackStack
からキーが取り除かれたら、ViewModel のリソースも開放する
Navigation とViewModel Navigation とViewModel を組み合わせるときに必要になる考慮 遷移先へのデータ授受 ex. 商品一覧画面→商品詳細画面への遷移 商品ID を渡す
素のままだと 機能に 乏しいので NavEntryDecorator を 使って 拡張します
NavEntryDecorator NavEntry の機能を拡張するための仕組み // navEntryDecorator ファクトリ関数を使って作る @Composable fun rememberLogNavEntryDecorator() =
remember { navEntryDecorator<Any>( onPop = { key -> // NavEntryがBackStackから離れるときに実行する処理 }, decorator = { entry -> // NavEntryがBackStackに追加されたときに実行する処理 entry.Content() } ) } // より複雑なことをやりたい場合は `NavEntryDecorator<Any>` を継承してから作る public fun ComplexNavEntryDecorator(): NavEntryDecorator<Any> { // ... }
NavEntryDecorator NavEntry の機能を拡張するための仕組み // ex. BackStackのライフサイクルをログ出力するためのNavEntryDecorator // star-zeroさんの記事を参考にしてます // https://star-zero.medium.com/jetpack-navigation3%E3%81%AE%E6%84%9F%E6%83%B3-440c600dc143
@Composable fun rememberLogNavEntryDecorator() = remember { navEntryDecorator<Any>( onPop = { key -> Log.d("$key", "POP: $key") }, decorator = { entry -> LaunchedEffect(Unit) { Log.d("${entry.contentKey}", "ENTER: ${entry.contentKey}") } entry.Content() } ) }
定義済みのNavEntryDecorator SceneSetupNavEntryDecorator 重複レンダリング防止 NavEntry の状態を保持したまま移動可能にしている(moveableContentOf を利用) アニメーション対応 SavedStateNavEntryDecorator rememberSaveable で保存した状態のライフサイクルをNavEntry
に合わせる NavEntry をスコープとしたSavedState 対応 ViewModelStoreNavEntryDecorator ViewModel のライフサイクルをNavEntry に合わせる NavEntry をViewModelStore として扱えるようにする SavedStateHandle を利用可能にする
使い方 val backStack = rememberNavBackStack(HomeRoute) NavDisplay( entryDecorators = listOf( rememberSceneSetupNavEntryDecorator(),
rememberSavedStateNavEntryDecorator(), rememberViewModelStoreNavEntryDecorator(), ), backStack = backStack, entryProvider = entryProvider { entry<HomeRoute> { val viewModel = hiltViewModel<HomeViewModel>() // ... } entry<ItemsRoute> { val viewModel = hiltViewModel<ItemsViewModel>() // ... } } ) create BackStack
使い方 entryDecorators = listOf( rememberSceneSetupNavEntryDecorator(), rememberSavedStateNavEntryDecorator(), rememberViewModelStoreNavEntryDecorator(), ), val backStack
= rememberNavBackStack(HomeRoute) NavDisplay( backStack = backStack, entryProvider = entryProvider { entry<HomeRoute> { val viewModel = hiltViewModel<HomeViewModel>() // ... } entry<ItemsRoute> { val viewModel = hiltViewModel<ItemsViewModel>() // ... } } ) setup entryDecorators List として渡す Modifier と同様に登録順が挙動に影響を 与える
使い方 val viewModel = hiltViewModel<HomeViewModel>() val viewModel = hiltViewModel<ItemsViewModel>() val
backStack = rememberNavBackStack(HomeRoute) NavDisplay( entryDecorators = listOf( rememberSceneSetupNavEntryDecorator(), rememberSavedStateNavEntryDecorator(), rememberViewModelStoreNavEntryDecorator(), ), backStack = backStack, entryProvider = entryProvider { entry<HomeRoute> { // ... } entry<ItemsRoute> { // ... } } ) create viewmodel by hiltViewModel() hilt-navigation-compose は navigation-compose 専用というわけでは ないのでNavigation3 でも引き続き利用可 能
使い方 val backStack = rememberNavBackStack(HomeRoute) NavDisplay( entryDecorators = listOf( rememberSceneSetupNavEntryDecorator(),
rememberSavedStateNavEntryDecorator(), rememberViewModelStoreNavEntryDecorator(), ), backStack = backStack, entryProvider = entryProvider { entry<HomeRoute> { val viewModel = hiltViewModel<HomeViewModel>() // ... } entry<ItemsRoute> { val viewModel = hiltViewModel<ItemsViewModel>() // ... } } ) ここまででNavEntry-aware なViewModel のセットアップが完了 → つぎはViewModel へのデータの授受
SavedStateHandle 経由でデータを受け取る @HiltViewModel class ItemViewModel @Inject constructor( private val hogeUseCase:
HogeUseCase, private val fugaRepository: FugaRepository, savedStateHandle: SavedStateHandle, ): ViewModel() { private val itemId = savedStateHandle["itemId"] // こんな感じでデータを受け取りたい }
SavedStateHandle 経由でデータを受け取る @HiltViewModel class ItemViewModel @Inject constructor( private val hogeUseCase:
HogeUseCase, private val fugaRepository: FugaRepository, savedStateHandle: SavedStateHandle, ): ViewModel() { private val itemId = savedStateHandle["itemId"] // こんな感じでデータを受け取りたい } // ver. navigation-compose navController.navigate(ItemRoute(itemId)) // → これでいける!
SavedStateHandle 経由でデータを受け取る @HiltViewModel class ItemViewModel @Inject constructor( private val hogeUseCase:
HogeUseCase, private val fugaRepository: FugaRepository, savedStateHandle: SavedStateHandle, ): ViewModel() { private val itemId = savedStateHandle["itemId"] // こんな感じでデータを受け取りたい } // ver. navigation-compose navController.navigate(ItemRoute(itemId)) // → これでいける! // ver. navigation3 backStack.add(ItemRoute(itemId)) // → これでいける?
SavedStateHandle 経由でデータを受け取る null 。 。 だと。 。 init { Log.d("ItemViewModel",
"itemId: ${savedStateHandle.get<String>("itemId")}") }
天下のGoogle 様がそんなことするはずないよね
天下のGoogle 様がそんなことするはずないよね サンプル実装(nav3-recipe) ViewModelProvider.Factory を自前実装してデータを直 接受け取っている
天下のGoogle 様がそんなことするはずないよね サンプル実装(nav3-recipe) Factory を実装して AssistedInject でデータを直接 受け取っている
SavedStateHandle に データを 詰める ところまで 対応できてない or しない 疑惑
現状の対応方法: AssistedInject を使って部分DI する @HiltViewModel(assistedFactory = ItemViewModel.Factory::class) class ItemViewModel @AssistedInject
constructor( private val hogeUseCase: HogeUseCase, private val fugaRepository: FugaRepository, @Assisted private val route: ItemRoute, ): ViewModel() { // ... @AssistedFactory interface Factory { fun create(route: ItemRoute): ItemViewModel } } entery<ItemRoute> { route -> val viewModel = hiltViewModel { factory: ItemViewModel.Factory -> factory.create(route) } }
なぜSavedStateHandle にデータが格納されないの か。その理由を探るため我々はViewModel の奥地へと 歩みを進めた。 。 インスタンスはどこからやってくるのか viewModels() ViewModelLazy ViewModelProvider
ViewModelProvider.Factory CreationExtras viewModelFactory {}
なぜSavedStateHandle にデータが格納されないの か。その理由を探るため我々はViewModel の奥地へと 歩みを進めた。 。 どうやって構成変更を生き延びているのか onRetainNonConfigurationInstance ViewModelStore ViewModelStoreOwner
なぜSavedStateHandle にデータが格納されないの か。その理由を探るため我々はViewModel の奥地へと 歩みを進めた。 。 どうやってOS によるプロセスデスを生き延びているのか onSaveInstanceState SavedStateRegistry
SavedStateRegistryController SavedStateRegistryOwner SavedStateProvider SavedStateHandle SavedStateHandlesProvider SavedStateHandlesProvider.SavedStateHandlesVM SavedStateViewModelFactory enableSavedStateHandles
なぜSavedStateHandle にデータが格納されないの か。その理由を探るため我々はViewModel の奥地へと 歩みを進めた。 。 Navigation3 ではViewModelStore, SavedStateHandle はどうやって統合するのか
SavedStateNavEntryDecorator ViewModelStoreNavEntryDecorator
TO BE CONTINUE...
まとめ Navigation3 には機能を拡張する仕組みとしてNavEntryDecorator がある Navigation3 でViewModel を使うためにはSavedStateNavEntryDecorator と ViewModelStoreNavEntryDecorator を組み合わせて使う
( いまのところ) SavedStateHandle にはデータが入ってこない AAC ViewModel を今一度ちゃんと理解する必要があるのかもしれない