"Cannot create an instance of class" when trying to use hilt view model with Jetpack Composable – dagger Hilt + Jetpack Compose

huangapple go评论108阅读模式
英文:

"Cannot create an instance of class" when trying to use hilt view model with Jetpack Composable - dagger Hilt + Jetpack Compose

问题

我正在尝试在MainActivity中的@Composable中使用TodoViewModel

MainActivity.kt

class MainActivity : ComponentActivity() {
    // ...
}

@Composable
fun TodoInput(
    todoViewModel: TodoViewModel = hiltViewModel()
){
    // ...
}

TodoViewModel.kt

package com.example.todobasics.viewModel
// ...
@HiltViewModel
class TodoViewModel @Inject constructor(
    private val todoRepository: TodoRepository
) : ViewModel() {
    // ...
    fun saveTodo(title: String){
        // ...
    }
}

错误信息

FATAL EXCEPTION: main

Process: com.example.todobasics, PID: 6503

java.lang.RuntimeException: Cannot create an instance of class com.example.todobasics.viewModel.TodoViewModel

我还会附上我的AppModulebuild.gradle以供参考

AppModule.kt

package com.example.todobasics.di
// ...
@Module
@InstallIn(SingletonComponent::class)
object AppModule {
    // ...
}

build.gradle (:app)

plugins {
    id 'com.android.application'
    id 'org.jetbrains.kotlin.android'
    id 'kotlin-android'
    id 'kotlin-kapt'
    id 'com.google.dagger.hilt.android'
}
// ...
dependencies {
    implementation 'androidx.core:core-ktx:1.8.0'
    // ...
}
英文:

I am trying to use a TodoViewModel inside a @Composable in MainActivity

MainActivity.kt

class MainActivity : ComponentActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        setContent {
            TodoBasicsTheme {
                // A surface container using the 'background' color from the theme
                Surface(
                    modifier = Modifier.fillMaxSize(),
                    color = MaterialTheme.colorScheme.background
                ) {
                    TodoInput()
                }
            }
        }
    }
}

@Composable
fun TodoInput(
    todoViewModel: TodoViewModel = hiltViewModel()
){
    // val todoViewModel: TodoViewModel = viewModel()
    // val todoViewModel: TodoViewModel = hiltViewModel()

    var text by remember { mutableStateOf("Hello") }

    Row() {
        InputField(text = text, onValueChanged = { text = it }, label = "Enter Todo")
        Spacer(modifier = Modifier.width(10.dp))
        ExtendedFloatingActionButton(onClick = {
            todoViewModel.saveTodo(title = text)
        }) {
            Text(text = "Add")
        }
    }
}

TodoViewModel.kt

package com.example.todobasics.viewModel

imports...

@HiltViewModel
class TodoViewModel @Inject constructor(
    private val todoRepository: TodoRepository
) : ViewModel() {
    val LOG_TAG = "todoViewModel"
    init {
        println("Hello")
    }
    fun saveTodo(title: String){
        Log.i(LOG_TAG, "Saving Todo")

        viewModelScope.launch(Dispatchers.Default){
            todoRepository.insertTodo(Todo(title=title))
        }
    }
}

Error Message

FATAL EXCEPTION: main

Process: com.example.todobasics, PID: 6503

java.lang.RuntimeException: Cannot create an instance of class com.example.todobasics.viewModel.TodoViewModel

I am also adding my AppModule and build.gradle for additional information

AppModule.kt

package com.example.todobasics.di

imports...

@Module
@InstallIn(SingletonComponent::class)
object AppModule {

    @Provides
    @Singleton
    fun provideTripMemoryDatabase(app: Application): TodoDatabase{
        return Room.databaseBuilder(
            app,
            TodoDatabase::class.java,
            "todo_db"
        ).build()

    }

    @Provides
    @Singleton
    fun provideTodoRepository(db: TodoDatabase): TodoRepository{
        return TodoRepository(db.todoDao)
    }
}

build.gradle (:app)

plugins {
    id 'com.android.application'
    id 'org.jetbrains.kotlin.android'
    id 'kotlin-android'
    id 'kotlin-kapt'
    id 'com.google.dagger.hilt.android'
}

android {
    namespace 'com.example.todobasics'
    compileSdk 34

    defaultConfig {
        applicationId "com.example.todobasics"
        minSdk 24
        targetSdk 34
        versionCode 1
        versionName "1.0"

        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
        vectorDrawables {
            useSupportLibrary true
        }
    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
    kotlinOptions {
        jvmTarget = '1.8'
    }
    buildFeatures {
        compose true
    }
    composeOptions {
        kotlinCompilerExtensionVersion '1.3.2'
    }
    packagingOptions {
        resources {
            excludes += '/META-INF/{AL2.0,LGPL2.1}'
        }
    }
}

dependencies {
    implementation 'androidx.core:core-ktx:1.8.0'
    implementation platform('org.jetbrains.kotlin:kotlin-bom:1.8.0')
    implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.3.1'
    implementation 'androidx.activity:activity-compose:1.5.1'
    implementation platform('androidx.compose:compose-bom:2022.10.00')
    implementation 'androidx.compose.ui:ui'
    implementation 'androidx.compose.ui:ui-graphics'
    implementation 'androidx.compose.ui:ui-tooling-preview'
    implementation 'androidx.compose.material3:material3'
    implementation 'androidx.core:core-ktx:+'
    testImplementation 'junit:junit:4.13.2'
    androidTestImplementation 'androidx.test.ext:junit:1.1.5'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
    androidTestImplementation platform('androidx.compose:compose-bom:2022.10.00')
    androidTestImplementation 'androidx.compose.ui:ui-test-junit4'
    debugImplementation 'androidx.compose.ui:ui-tooling'
    debugImplementation 'androidx.compose.ui:ui-test-manifest'
    // Compose Navigation
    implementation("androidx.navigation:navigation-compose:$nav_version") // 2.5.3
    // Room
    implementation("androidx.room:room-runtime:$room_version")
    kapt("androidx.room:room-compiler:$room_version")
    implementation("androidx.room:room-ktx:$room_version")

    // optional - Kotlin Extensions and Coroutines support for Room
    implementation("androidx.room:room-ktx:$room_version")

    // Dagger Hilt
    implementation "com.google.dagger:hilt-android:$dagger_version"
    kapt "com.google.dagger:hilt-compiler:$dagger_version"
    implementation("androidx.hilt:hilt-navigation-compose:1.0.0")

    // ViewModel
    implementation("androidx.lifecycle:lifecycle-viewmodel-ktx:$lifecycle_version")
    implementation("androidx.lifecycle:lifecycle-viewmodel-compose:$lifecycle_version")

}

kapt {
    correctErrorTypes = true
}

答案1

得分: 1

To enable members injection in your activity, annotate your class with @AndroidEntryPoint.

要启用成员注入在您的活动中,请使用**@AndroidEntryPoint**注释您的类。

You forget to add @AndroidEntryPoint on MainActivity, Just Add It And You will have no error.

您忘记在MainActivity上添加**@AndroidEntryPoint**,只需添加它,您将不会有错误。

@AndroidEntryPoint
class MainActivity : ComponentActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        setContent {
            TodoBasicsTheme {
                // A surface container using the 'background' color from the theme
                Surface(
                    modifier = Modifier.fillMaxSize(),
                    color = MaterialTheme.colorScheme.background
                ) {
                    TodoInput()
                }
            }
        }
    }
}

@Composable
fun TodoInput(
    todoViewModel: TodoViewModel = hiltViewModel()
){
    var text by remember { mutableStateOf("Hello") }

    Row() {
        InputField(text = text, onValueChanged = { text = it }, label = "Enter Todo")
        Spacer(modifier = Modifier.width(10.dp))
        ExtendedFloatingActionButton(onClick = {
            todoViewModel.saveTodo(title = text)
        }) {
            Text(text = "Add")
        }
    }
}

Note: The code part has not been translated.

英文:

To enable members injection in your activity, annotate your class with @AndroidEntryPoint.

You forget to add @AndroidEntryPoint on MainActivity, Just Add It And You will have no error

@AndroidEntryPoint
    class MainActivity : ComponentActivity() {
    
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
    
            setContent {
                TodoBasicsTheme {
                    // A surface container using the 'background' color from the theme
                    Surface(
                        modifier = Modifier.fillMaxSize(),
                        color = MaterialTheme.colorScheme.background
                    ) {
                        TodoInput()
                    }
                }
            }
        }
    }
    
    @Composable
    fun TodoInput(
        todoViewModel: TodoViewModel = hiltViewModel()
    ){
        // val todoViewModel: TodoViewModel = viewModel()
        // val todoViewModel: TodoViewModel = hiltViewModel()
    
        var text by remember { mutableStateOf("Hello") }
    
        Row() {
            InputField(text = text, onValueChanged = { text = it }, label = "Enter Todo")
            Spacer(modifier = Modifier.width(10.dp))
            ExtendedFloatingActionButton(onClick = {
                todoViewModel.saveTodo(title = text)
            }) {
                Text(text = "Add")
            }
        }
    }

huangapple
  • 本文由 发表于 2023年6月12日 19:39:45
  • 转载请务必保留本文链接:https://go.coder-hub.com/76456302.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定