背景
在使用ViewModel时,一般会考虑使用hilt来依赖注入ViewModel对象。在使用compose时,安卓官方推荐使用androidx.hilt.lifecycle.viewmodel.compose库中的hiltViewModel()方法,来注入ViewModel对象
在Nav3中使用Hilt注入ViewModel对象
- 配置环境
- 完善
lifecycle-viewmodel-navigation3库配置 - 使用
hiltViewModel()完成对象注入
环境配置
- 导入Nav3相关库
- 导入
androidx.hilt.lifecycle.viewmodel.compose库 - 导入
Hilt相关库 - 导入
lifecycle-viewmodel-navigation3库
使用案例
/*
* 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
}
}
相关参考文献