Jetpack 使用 HiltViewModel 组合导航:MainActivity 未实现接口 dagger.hilt.internal.GeneratedComponent
Jetpack Compose Navigation with HiltViewModel: MainActivity does not implement interface dagger.hilt.internal.GeneratedComponent
我创建了一个新的可组合 activity 项目,具有以下依赖项:
implementation "androidx.navigation:navigation-compose:2.4.0-alpha09"
implementation "com.google.dagger:hilt-android:2.38.1"
implementation "androidx.hilt:hilt-navigation-compose:1.0.0-alpha03"
然后我创建了两个可组合项,一个带有 Hilt 的视图模型:
@Composable
fun Screen1(onClick: () -> Unit) {
Column {
Text(text = "Screen 1")
Button(onClick = onClick) {
Text("To Screen 2")
}
}
}
@HiltViewModel
class Screen2ViewModel @Inject constructor() : ViewModel()
@Composable
fun Screen2(viewModel: Screen2ViewModel = hiltViewModel()) {
Text(text = "Screen 2")
}
如果我尝试渲染它们,它会起作用。但是,当我添加 NavController:
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
val navController = rememberNavController()
MyApplicationTheme {
// A surface container using the 'background' color from the theme
Surface(color = MaterialTheme.colors.background) {
NavHost(navController = navController, startDestination = "screen1") {
composable("screen1") {
Screen1() {
navController.navigate("screen2")
}
}
composable("screen2") {
Screen2()
}
}
}
}
}
}
}
当我转到屏幕 2 时,我的应用程序崩溃并出现以下错误:
java.lang.IllegalStateException: Given component holder class com.sample.myapplication.MainActivity does not implement interface dagger.hilt.internal.GeneratedComponent or interface dagger.hilt.internal.GeneratedComponentManager
我做错了什么?
完整代码:
package com.sample.myapplication
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.Column
import androidx.compose.material.Button
import androidx.compose.material.MaterialTheme
import androidx.compose.material.Surface
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.lifecycle.ViewModel
import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable
import androidx.navigation.compose.rememberNavController
import com.sample.myapplication.ui.theme.MyApplicationTheme
import dagger.hilt.android.AndroidEntryPoint
import dagger.hilt.android.lifecycle.HiltViewModel
import javax.inject.Inject
@AndroidEntryPoint
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
val navController = rememberNavController()
MyApplicationTheme {
// A surface container using the 'background' color from the theme
Surface(color = MaterialTheme.colors.background) {
NavHost(navController = navController, startDestination = "screen1") {
composable("screen1") {
Screen1() {
navController.navigate("screen2")
}
}
composable("screen2") {
Screen2()
}
}
}
}
}
}
}
@Composable
fun Screen1(onClick: () -> Unit) {
Column {
Text(text = "Screen 1")
Button(onClick = onClick) {
Text("To Screen 2")
}
}
}
@HiltViewModel
class Screen2ViewModel @Inject constructor() : ViewModel()
@Composable
fun Screen2(viewModel: Screen2ViewModel = hiltViewModel()) {
Text(text = "Screen 2")
}
只需确认您在 Activity
上添加了 @AndroidEntryPoint
注释,在 ViewModel
上添加了 @HiltViewModel
注释。
这两个更新将解决此问题。
根据HiltViewModel
的文档
Returns an existing HiltViewModel -annotated ViewModel or creates a new one scoped to the current navigation graph present on the {@link NavController} back stack.
If no navigation graph is currently present then the current scope will be used, usually, a fragment or an activity.
要解决此问题,我们有两个解决方案:
- 使用
import androidx.lifecycle.viewmodel.compose.viewModel
中的 viewModel()
- 将
hiltViewModel()
的实例范围限定到 activity 并传递给 Screen2()
- 需要应用 Hilt 插件作为下一个答案:
向应用添加更多内容
build.gradle
apply plugin: kotlin-kapt
- 将刀柄 android 编译器添加到依赖项
kapt "com.google.dagger:hilt-android-compiler:2.40"
创建应用程序的扩展并使用 @HiltAndroidApp
进行注释并在您的应用程序中使用。
应用 @AndroidEntryPoint
注释本身不会执行任何操作 - 它是一个标记注释,允许 Hilt Gradle Plugin 处理您的代码并生成使 Hilt 正常工作所需的正确字节码。您需要确保插件已应用:
buildscript {
repositories {
// other repositories...
mavenCentral()
}
dependencies {
// other plugins...
classpath 'com.google.dagger:hilt-android-gradle-plugin:2.40'
}
}
apply plugin: 'com.android.application'
apply plugin: 'dagger.hilt.android.plugin'
android {
// ...
}
我创建了一个新的可组合 activity 项目,具有以下依赖项:
implementation "androidx.navigation:navigation-compose:2.4.0-alpha09"
implementation "com.google.dagger:hilt-android:2.38.1"
implementation "androidx.hilt:hilt-navigation-compose:1.0.0-alpha03"
然后我创建了两个可组合项,一个带有 Hilt 的视图模型:
@Composable
fun Screen1(onClick: () -> Unit) {
Column {
Text(text = "Screen 1")
Button(onClick = onClick) {
Text("To Screen 2")
}
}
}
@HiltViewModel
class Screen2ViewModel @Inject constructor() : ViewModel()
@Composable
fun Screen2(viewModel: Screen2ViewModel = hiltViewModel()) {
Text(text = "Screen 2")
}
如果我尝试渲染它们,它会起作用。但是,当我添加 NavController:
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
val navController = rememberNavController()
MyApplicationTheme {
// A surface container using the 'background' color from the theme
Surface(color = MaterialTheme.colors.background) {
NavHost(navController = navController, startDestination = "screen1") {
composable("screen1") {
Screen1() {
navController.navigate("screen2")
}
}
composable("screen2") {
Screen2()
}
}
}
}
}
}
}
当我转到屏幕 2 时,我的应用程序崩溃并出现以下错误:
java.lang.IllegalStateException: Given component holder class com.sample.myapplication.MainActivity does not implement interface dagger.hilt.internal.GeneratedComponent or interface dagger.hilt.internal.GeneratedComponentManager
我做错了什么?
完整代码:
package com.sample.myapplication
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.Column
import androidx.compose.material.Button
import androidx.compose.material.MaterialTheme
import androidx.compose.material.Surface
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.lifecycle.ViewModel
import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable
import androidx.navigation.compose.rememberNavController
import com.sample.myapplication.ui.theme.MyApplicationTheme
import dagger.hilt.android.AndroidEntryPoint
import dagger.hilt.android.lifecycle.HiltViewModel
import javax.inject.Inject
@AndroidEntryPoint
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
val navController = rememberNavController()
MyApplicationTheme {
// A surface container using the 'background' color from the theme
Surface(color = MaterialTheme.colors.background) {
NavHost(navController = navController, startDestination = "screen1") {
composable("screen1") {
Screen1() {
navController.navigate("screen2")
}
}
composable("screen2") {
Screen2()
}
}
}
}
}
}
}
@Composable
fun Screen1(onClick: () -> Unit) {
Column {
Text(text = "Screen 1")
Button(onClick = onClick) {
Text("To Screen 2")
}
}
}
@HiltViewModel
class Screen2ViewModel @Inject constructor() : ViewModel()
@Composable
fun Screen2(viewModel: Screen2ViewModel = hiltViewModel()) {
Text(text = "Screen 2")
}
只需确认您在 Activity
上添加了 @AndroidEntryPoint
注释,在 ViewModel
上添加了 @HiltViewModel
注释。
这两个更新将解决此问题。
根据HiltViewModel
Returns an existing HiltViewModel -annotated ViewModel or creates a new one scoped to the current navigation graph present on the {@link NavController} back stack. If no navigation graph is currently present then the current scope will be used, usually, a fragment or an activity.
要解决此问题,我们有两个解决方案:
- 使用
import androidx.lifecycle.viewmodel.compose.viewModel
中的 - 将
hiltViewModel()
的实例范围限定到 activity 并传递给Screen2()
- 需要应用 Hilt 插件作为下一个答案:
向应用添加更多内容
build.gradle
viewModel()
apply plugin: kotlin-kapt
- 将刀柄 android 编译器添加到依赖项
kapt "com.google.dagger:hilt-android-compiler:2.40"
创建应用程序的扩展并使用@HiltAndroidApp
进行注释并在您的应用程序中使用。
应用 @AndroidEntryPoint
注释本身不会执行任何操作 - 它是一个标记注释,允许 Hilt Gradle Plugin 处理您的代码并生成使 Hilt 正常工作所需的正确字节码。您需要确保插件已应用:
buildscript {
repositories {
// other repositories...
mavenCentral()
}
dependencies {
// other plugins...
classpath 'com.google.dagger:hilt-android-gradle-plugin:2.40'
}
}
apply plugin: 'com.android.application'
apply plugin: 'dagger.hilt.android.plugin'
android {
// ...
}