我正在尝试在 android kotlin 中学习 Dagger/Hilt 依赖注入。我准备了一个简单的小应用程序。当我运行应用程序时,出现以下错误:
C:\XXXXX\AndroidLearning\MyTest\app\build\generated\hilt\component_sources\debug\com\example\mytest\MyTest_HiltComponents.java:125: error: [Dagger/MissingBinding] com.example.mytest.MyTestInjectionClass cannot be provided without an @Inject constructor or an @Provides-annotated method.
public abstract static class SingletonC implements MyTest_GeneratedInjector,
^
com.example.mytest.MyTestInjectionClass is injected at
com.example.mytest.MyViewModel(myTestInjectionClass)
com.example.mytest.MyViewModel is injected at
com.example.mytest.MyViewModel_HiltModules.BindsModule.binds(arg0)
@dagger.hilt.android.internal.lifecycle.HiltViewModelMap java.util.Map<java.lang.String,javax.inject.Provider<androidx.lifecycle.ViewModel>> is requested at
dagger.hilt.android.internal.lifecycle.HiltViewModelFactory.ViewModelFactoriesEntryPoint.getHiltViewModelMap() [com.example.mytest.MyTest_HiltComponents.SingletonC ? com.example.mytest.MyTest_HiltComponents.ActivityRetainedC ? com.example.mytest.MyTest_HiltComponents.ViewModelC]
在我的应用程序中,viewModel 类使用
@HiltViewModel
注释进行注释。我也有 @Inject
视图模型类构造函数的注释。我正在注入一个名为“MyInjectionClass”的类。我创建了一个模块,并在其中用“@Provides”和“@Singleton”注释了函数。我正在包含应用程序中的文件
项目build.gradle文件
buildscript {
ext {
compose_version = '1.2.0'
}
}// Top-level build file where you can add configuration options common to all sub-projects/modules.
plugins {
id 'com.android.application' version '7.4.0' apply false
id 'com.android.library' version '7.4.0' apply false
id 'org.jetbrains.kotlin.android' version '1.7.0' apply false
id("com.google.dagger.hilt.android") version "2.44" apply false
}
app build.gradle 文件
plugins {
id 'com.android.application'
id 'org.jetbrains.kotlin.android'
id("kotlin-kapt")
id("dagger.hilt.android.plugin")
}
android {
namespace 'com.example.mytest'
compileSdk 33
defaultConfig {
applicationId "com.example.mytest"
minSdk 29
targetSdk 33
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.2.0'
}
packagingOptions {
resources {
excludes += '/META-INF/{AL2.0,LGPL2.1}'
}
}
}
dependencies {
def lifecycle_version = "2.5.1"
def retrofit_version = "2.9.0"
def gson_version = "2.9.0"
def room_version = "2.5.0"
def nav_version = "2.5.3"
def compose_version = "1.3.3"
def preference_version = "1.2.0"
implementation 'androidx.core:core-ktx:1.7.0'
implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.3.1'
implementation 'androidx.activity:activity-compose:1.3.1'
implementation "androidx.compose.ui:ui:$compose_version"
implementation "androidx.compose.ui:ui-tooling-preview:$compose_version"
implementation 'androidx.compose.material3:material3:1.0.0-alpha11'
// Dagger - hilt
implementation 'com.google.dagger:hilt-android:2.44.2'
kapt 'com.google.dagger:hilt-compiler:2.44.2'
implementation 'androidx.hilt:hilt-navigation-compose:1.0.0'
//lifecycle
// ViewModel
implementation("androidx.lifecycle:lifecycle-viewmodel-ktx:$lifecycle_version")
// ViewModel utilities for Compose
implementation("androidx.lifecycle:lifecycle-viewmodel-compose:$lifecycle_version")
implementation("androidx.lifecycle:lifecycle-runtime-compose:2.6.0-alpha03")
implementation "androidx.compose.runtime:runtime-livedata:$compose_version"
implementation("androidx.compose.runtime:runtime:$compose_version")
kapt("androidx.lifecycle:lifecycle-compiler:$lifecycle_version")
//couroutines
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.9")
implementation("androidx.lifecycle:lifecycle-viewmodel-ktx:$lifecycle_version")
implementation("androidx.lifecycle:lifecycle-runtime-ktx:$lifecycle_version")
implementation("androidx.lifecycle:lifecycle-livedata-ktx:$lifecycle_version")
//navigation in compose
implementation("androidx.navigation:navigation-compose:$nav_version")
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.5'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
androidTestImplementation "androidx.compose.ui:ui-test-junit4:$compose_version"
debugImplementation "androidx.compose.ui:ui-tooling:$compose_version"
debugImplementation "androidx.compose.ui:ui-test-manifest:$compose_version"
mainactivity.kt 文件
@AndroidEntryPoint
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
MyTestTheme {
val myViewModel = hiltViewModel<MyViewModel>()
val myText1 = myViewModel.myText.observeAsState()
val myText2 = ""
// A surface container using the 'background' color from the theme
Surface(
modifier = Modifier.fillMaxSize(),
color = MaterialTheme.colorScheme.background
) {
Text(myText1.value!!.myText!!)
TextField(value = myText2, onValueChange = {myViewModel.testFunction(myText2)})
}
}
}
}
}
MyViewModel.kt 文件
@HiltViewModel
class MyViewModel @Inject constructor(
private val myTestInjectionClass: MyTestInjectionClass
) : ViewModel() {
var temp = MyModel()
var myText = MutableLiveData<MyModel?>(temp)
fun testFunction(text:String) = viewModelScope.launch {
myText.value = myTestInjectionClass.execute(text)
}
}
MyTest是应用类
@HiltAndroidApp
class MyTest : Application() {
}
我的模型.kt
data class MyModel(
var myText: String? = ""
)
MyTestInjectionClass.kt
class MyTestInjectionClass() {
suspend fun execute(text:String) : MyModel {
delay(2000)
var myModel = MyModel()
myModel.myText =text.uppercase()
return myModel;
}
}
一个测试模块.kt
@Module
@InstallIn(SingletonComponent::class)
class MyTestModule {
@Singleton
@Provides
suspend fun provideAMyTestInjectionClass() : MyTestInjectionClass {
return MyTestInjectionClass()
}
}
有人可以帮我解决这个错误吗?谢谢
当我删除
MyTestModule.kt
文件中的函数之前的 suspend 关键字时,它起作用了
@Module
@InstallIn(SingletonComponent::class)
class MyTestModule {
@Singleton
@Provides
fun provideAMyTestInjectionClass() : MyTestInjectionClass {
return MyTestInjectionClass()
}
}
~~~