Оптимизируйте свои подборки
Сохраняйте и классифицируйте контент в соответствии со своими настройками.
Передача аргументов в ViewModel (Hilt)
В этом примере показано, как передавать аргументы навигации (ключи) в ViewModel , используя Hilt для внедрения зависимостей.
Как это работает
В этом примере используется функция автоматической инъекции Dagger/Hilt:
-
ViewModel аннотируется с помощью @HiltViewModel , а его конструктор использует @AssistedInject для получения клавиши навигации (которая также аннотируется с помощью @Assisted ). - Для создания
ViewModel определен интерфейс @AssistedFactory . - Функция
hiltViewModel , допускающая компонуемость, используется для получения экземпляра ViewModel . Предоставляется функция creationCallback для передачи навигационной клавиши в фабрику, делая её доступной для ViewModel .
Примечание : Декоратор rememberViewModelStoreNavEntryDecorator добавляется к entryDecorators объекта NavDisplay . Это гарантирует, что ViewModel корректно привязаны к соответствующему NavEntry , так что для каждой уникальной навигационной клавиши создается новый экземпляр ViewModel .

Исследовать
Полный рецепт можно посмотреть на GitHub.
arrow_forward /*
* Copyright 2025 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.example.nav3recipes.passingarguments.viewmodels.hilt
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.material3.Button
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.mutableStateListOf
import androidx.compose.runtime.remember
import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel
import androidx.lifecycle.ViewModel
import androidx.lifecycle.compose.dropUnlessResumed
import androidx.lifecycle.viewmodel.navigation3.rememberViewModelStoreNavEntryDecorator
import androidx.navigation3.runtime.entryProvider
import androidx.navigation3.runtime.rememberSaveableStateHolderNavEntryDecorator
import androidx.navigation3.ui.NavDisplay
import com.example.nav3recipes.content.ContentBlue
import com.example.nav3recipes.content.ContentGreen
import com.example.nav3recipes.passingarguments.viewmodels.basic.RouteB
import com.example.nav3recipes.ui.setEdgeToEdgeConfig
import dagger.assisted.Assisted
import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject
import dagger.hilt.android.AndroidEntryPoint
import dagger.hilt.android.lifecycle.HiltViewModel
data object RouteA
data class RouteB(val id: String)
@AndroidEntryPoint
class HiltViewModelsActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
setEdgeToEdgeConfig()
super.onCreate(savedInstanceState)
setContent {
val backStack = remember { mutableStateListOf<Any>(RouteA) }
NavDisplay(
backStack = backStack,
onBack = { backStack.removeLastOrNull() },
// In order to add the `ViewModelStoreNavEntryDecorator` (see comment below for why)
// we also need to add the default `NavEntryDecorator`s as well. These provide
// extra information to the entry's content to enable it to display correctly
// and save its state.
entryDecorators = listOf(
rememberSaveableStateHolderNavEntryDecorator(),
rememberViewModelStoreNavEntryDecorator()
),
entryProvider = entryProvider {
entry<RouteA> {
ContentGreen("Welcome to Nav3") {
LazyColumn {
items(10) { i ->
Button(onClick = dropUnlessResumed {
backStack.add(RouteB("$i"))
}) {
Text("$i")
}
}
}
}
}
entry<RouteB> { key ->
val viewModel = hiltViewModel<RouteBViewModel, RouteBViewModel.Factory>(
// Note: We need a new ViewModel for every new RouteB instance. Usually
// we would need to supply a `key` String that is unique to the
// instance, however, the ViewModelStoreNavEntryDecorator (supplied
// above) does this for us, using `NavEntry.contentKey` to uniquely
// identify the viewModel.
//
// tl;dr: Make sure you use rememberViewModelStoreNavEntryDecorator()
// if you want a new ViewModel for each new navigation key instance.
creationCallback = { factory ->
factory.create(key)
}
)
ScreenB(viewModel = viewModel)
}
}
)
}
}
}
@Composable
fun ScreenB(viewModel: RouteBViewModel) {
ContentBlue("Route id: ${viewModel.navKey.id} ")
}
@HiltViewModel(assistedFactory = RouteBViewModel.Factory::class)
class RouteBViewModel @AssistedInject constructor(
@Assisted val navKey: RouteB
) : ViewModel() {
@AssistedFactory
interface Factory {
fun create(navKey: RouteB): RouteBViewModel
}
}
Передача аргументов в ViewModel (основы)
В этом примере показано, как передавать аргументы навигации (ключи) в ViewModel с помощью пользовательского ViewModelProvider.Factory .
Как это работает
- Создается пользовательский
ViewModelProvider.Factory , который принимает ключ навигации в качестве параметра конструктора. - Внутри
entry composable используется viewModel(factory = ...) для создания экземпляра ViewModel , передавая текущий ключ навигации фабрике. Это делает ключ навигации доступным для ViewModel .
Примечание : Декоратор rememberViewModelStoreNavEntryDecorator добавляется к entryDecorators объекта NavDisplay . Это гарантирует, что ViewModel корректно привязаны к соответствующему NavEntry , так что для каждой уникальной навигационной клавиши создается новый экземпляр ViewModel .

Исследовать
Полный рецепт можно посмотреть на GitHub.
arrow_forward /*
* Copyright 2025 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.example.nav3recipes.passingarguments.viewmodels.basic
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.material3.Button
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.mutableStateListOf
import androidx.compose.runtime.remember
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.compose.dropUnlessResumed
import androidx.lifecycle.viewmodel.compose.viewModel
import androidx.lifecycle.viewmodel.navigation3.rememberViewModelStoreNavEntryDecorator
import androidx.navigation3.runtime.entryProvider
import androidx.navigation3.runtime.rememberSaveableStateHolderNavEntryDecorator
import androidx.navigation3.ui.NavDisplay
import com.example.nav3recipes.content.ContentBlue
import com.example.nav3recipes.content.ContentGreen
import com.example.nav3recipes.ui.setEdgeToEdgeConfig
data object RouteA
data class RouteB(val id: String)
class BasicViewModelsActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
setEdgeToEdgeConfig()
super.onCreate(savedInstanceState)
setContent {
val backStack = remember { mutableStateListOf<Any>(RouteA) }
NavDisplay(
backStack = backStack,
onBack = { backStack.removeLastOrNull() },
// In order to add the `ViewModelStoreNavEntryDecorator` (see comment below for why)
// we also need to add the default `NavEntryDecorator`s as well. These provide
// extra information to the entry's content to enable it to display correctly
// and save its state.
entryDecorators = listOf(
rememberSaveableStateHolderNavEntryDecorator(),
rememberViewModelStoreNavEntryDecorator()
),
entryProvider = entryProvider {
entry<RouteA> {
ContentGreen("Welcome to Nav3") {
LazyColumn {
items(10) { i ->
Button(onClick = dropUnlessResumed {
backStack.add(RouteB("$i"))
}) {
Text("$i")
}
}
}
}
}
entry<RouteB> { key ->
// Note: We need a new ViewModel for every new RouteB instance. Usually
// we would need to supply a `key` String that is unique to the
// instance, however, the ViewModelStoreNavEntryDecorator (supplied
// above) does this for us, using `NavEntry.contentKey` to uniquely
// identify the viewModel.
//
// tl;dr: Make sure you use rememberViewModelStoreNavEntryDecorator()
// if you want a new ViewModel for each new navigation key instance.
ScreenB(viewModel = viewModel(factory = RouteBViewModel.Factory(key)))
}
}
)
}
}
}
@Composable
fun ScreenB(viewModel: RouteBViewModel = viewModel()) {
ContentBlue("Route id: ${viewModel.key.id} ")
}
class RouteBViewModel(
val key: RouteB
) : ViewModel() {
class Factory(
private val key: RouteB,
) : ViewModelProvider.Factory {
override fun <T : ViewModel> create(modelClass: Class<T>): T {
return RouteBViewModel(key) as T
}
}
}
Передача аргументов в ViewModel (Koin)
В этом примере показано, как передавать аргументы навигации (ключи) в ViewModel с помощью Koin для внедрения зависимостей.
Как это работает
- Определен модуль Koin, предоставляющий
ViewModel . - Функция
koinViewModel , допускающая компонуемый тип, используется для получения экземпляра ViewModel . - Клавиша навигации передается в конструктор
ViewModel с помощью parametersOf(key) . Это делает клавишу навигации доступной для ViewModel .
Примечание : Декоратор rememberViewModelStoreNavEntryDecorator добавляется к entryDecorators объекта NavDisplay . Это гарантирует, что ViewModel корректно привязаны к соответствующему NavEntry , так что для каждой уникальной навигационной клавиши создается новый экземпляр ViewModel .

Исследовать
Полный рецепт можно посмотреть на GitHub.
arrow_forward package com.example.nav3recipes.passingarguments.viewmodels.koin
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.material3.Button
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.mutableStateListOf
import androidx.compose.runtime.remember
import androidx.lifecycle.ViewModel
import androidx.lifecycle.compose.dropUnlessResumed
import androidx.lifecycle.viewmodel.navigation3.rememberViewModelStoreNavEntryDecorator
import androidx.navigation3.runtime.entryProvider
import androidx.navigation3.runtime.rememberSaveableStateHolderNavEntryDecorator
import androidx.navigation3.ui.NavDisplay
import com.example.nav3recipes.content.ContentBlue
import com.example.nav3recipes.content.ContentGreen
import com.example.nav3recipes.ui.setEdgeToEdgeConfig
import org.koin.compose.KoinApplication
import org.koin.compose.viewmodel.koinViewModel
import org.koin.core.module.dsl.viewModelOf
import org.koin.core.parameter.parametersOf
import org.koin.dsl.koinConfiguration
import org.koin.dsl.module
data object RouteA
data class RouteB(val id: String)
class KoinViewModelsActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
setEdgeToEdgeConfig()
super.onCreate(savedInstanceState)
setContent {
val backStack = remember { mutableStateListOf<Any>(RouteA) }
// Koin Compose Entry point
KoinApplication(
configuration = koinConfiguration {
modules(appModule)
}
) {
NavDisplay(
backStack = backStack,
onBack = { backStack.removeLastOrNull() },
// In order to add the `ViewModelStoreNavEntryDecorator` (see comment below for why)
// we also need to add the default `NavEntryDecorator`s as well. These provide
// extra information to the entry's content to enable it to display correctly
// and save its state.
entryDecorators = listOf(
rememberSaveableStateHolderNavEntryDecorator(),
rememberViewModelStoreNavEntryDecorator()
),
entryProvider = entryProvider {
entry<RouteA> {
ContentGreen("Welcome to Nav3") {
LazyColumn {
items(10) { i ->
Button(onClick = dropUnlessResumed {
backStack.add(RouteB("$i"))
}) {
Text("$i")
}
}
}
}
}
entry<RouteB> { key ->
val viewModel = koinViewModel<RouteBViewModel> {
parametersOf(key)
}
ScreenB(viewModel = viewModel)
}
}
)
}
}
}
}
// Local Koin Module
private val appModule = module {
viewModelOf(::RouteBViewModel)
}
@Composable
fun ScreenB(viewModel: RouteBViewModel) {
ContentBlue("Route id: ${viewModel.navKey.id} ")
}
class RouteBViewModel(val navKey: RouteB) : ViewModel()
Контент и образцы кода на этой странице предоставлены по лицензиям. Java и OpenJDK – это зарегистрированные товарные знаки корпорации Oracle и ее аффилированных лиц.
Последнее обновление: 2026-05-09 UTC.