android - 找不到实现(房间)

标签 android kotlin android-room dagger-hilt

我在使用 Room 或 idk 时遇到问题,实际上问题出在哪里,我需要帮助找出问题出在哪里,我正在使用 Hilt DI,创建数据库实例的那一刻它崩溃了这是我的代码

错误

E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.example.todo, PID: 1895
    java.lang.RuntimeException: cannot find implementation for com.example.todo.data.ToDoDatabase. ToDoDatabase_Impl does not exist
        at androidx.room.Room.getGeneratedImplementation(Room.java:97)
        at androidx.room.RoomDatabase$Builder.build(RoomDatabase.java:1358)
        at com.example.todo.di.AppModule.provideToDoDatabase(AppModule.kt:27)
        at com.example.todo.di.AppModule_ProvideToDoDatabaseFactory.provideToDoDatabase(AppModule_ProvideToDoDatabaseFactory.java:33)
        at com.example.todo.DaggerMainApplication_HiltComponents_SingletonC.toDoDatabase(DaggerMainApplication_HiltComponents_SingletonC.java:69)
        at com.example.todo.DaggerMainApplication_HiltComponents_SingletonC.access$2000(DaggerMainApplication_HiltComponents_SingletonC.java:48)
        at com.example.todo.DaggerMainApplication_HiltComponents_SingletonC$SwitchingProvider.get(DaggerMainApplication_HiltComponents_SingletonC.java:583)
        at dagger.internal.DoubleCheck.get(DoubleCheck.java:47)
        at com.example.todo.DaggerMainApplication_HiltComponents_SingletonC.toDoDao(DaggerMainApplication_HiltComponents_SingletonC.java:73)
        at com.example.todo.DaggerMainApplication_HiltComponents_SingletonC.access$1900(DaggerMainApplication_HiltComponents_SingletonC.java:48)
        at com.example.todo.DaggerMainApplication_HiltComponents_SingletonC$SwitchingProvider.get(DaggerMainApplication_HiltComponents_SingletonC.java:580)
        at dagger.internal.DoubleCheck.get(DoubleCheck.java:47)
        at com.example.todo.DaggerMainApplication_HiltComponents_SingletonC$ViewModelCImpl.toDoRepository(DaggerMainApplication_HiltComponents_SingletonC.java:448)
        at com.example.todo.DaggerMainApplication_HiltComponents_SingletonC$ViewModelCImpl.toDoViewModel(DaggerMainApplication_HiltComponents_SingletonC.java:452)
        at com.example.todo.DaggerMainApplication_HiltComponents_SingletonC$ViewModelCImpl.access$1700(DaggerMainApplication_HiltComponents_SingletonC.java:429)
        at com.example.todo.DaggerMainApplication_HiltComponents_SingletonC$ViewModelCImpl$SwitchingProvider.get(DaggerMainApplication_HiltComponents_SingletonC.java:487)
        at dagger.hilt.android.internal.lifecycle.HiltViewModelFactory$1.create(HiltViewModelFactory.java:100)
        at androidx.lifecycle.AbstractSavedStateViewModelFactory.create(AbstractSavedStateViewModelFactory.java:69)
        at androidx.lifecycle.AbstractSavedStateViewModelFactory.create(AbstractSavedStateViewModelFactory.java:84)
        at dagger.hilt.android.internal.lifecycle.HiltViewModelFactory.create(HiltViewModelFactory.java:109)
        at androidx.lifecycle.ViewModelProvider.get(ViewModelProvider.kt:171)
        at androidx.lifecycle.ViewModelProvider.get(ViewModelProvider.kt:139)
        at androidx.lifecycle.ViewModelLazy.getValue(ViewModelLazy.kt:44)
        at androidx.lifecycle.ViewModelLazy.getValue(ViewModelLazy.kt:31)
        at com.example.todo.fragments.add.AddFragment.getViewModel(AddFragment.kt:20)
        at com.example.todo.fragments.add.AddFragment.insertDataToDo(AddFragment.kt:63)
        at com.example.todo.fragments.add.AddFragment.onOptionsItemSelected(AddFragment.kt:45)
        at androidx.fragment.app.Fragment.performOptionsItemSelected(Fragment.java:3122)
        at androidx.fragment.app.FragmentManager.dispatchOptionsItemSelected(FragmentManager.java:3226)
        at androidx.fragment.app.Fragment.performOptionsItemSelected(Fragment.java:3126)
        at androidx.fragment.app.FragmentManager.dispatchOptionsItemSelected(FragmentManager.java:3226)
        at androidx.fragment.app.FragmentController.dispatchOptionsItemSelected(FragmentController.java:416)
        at androidx.fragment.app.FragmentActivity.onMenuItemSelected(FragmentActivity.java:358)
        at androidx.appcompat.app.AppCompatActivity.onMenuItemSelected(AppCompatActivity.java:264)
        at androidx.appcompat.view.WindowCallbackWrapper.onMenuItemSelected(WindowCallbackWrapper.java:109)
        at androidx.appcompat.app.AppCompatDelegateImpl.onMenuItemSelected(AppCompatDelegateImpl.java:1179)
        at androidx.appcompat.view.menu.MenuBuilder.dispatchMenuItemSelected(MenuBuilder.java:834)
        at androidx.appcompat.view.menu.MenuItemImpl.invoke(MenuItemImpl.java:158)
        at androidx.appcompat.view.menu.MenuBuilder.performItemAction(MenuBuilder.java:985)
        at androidx.appcompat.view.menu.MenuBuilder.performItemAction(MenuBuilder.java:975)
        at androidx.appcompat.widget.ActionMenuView.invokeItem(ActionMenuView.java:624)
        at androidx.appcompat.view.menu.ActionMenuItemView.onClick(ActionMenuItemView.java:151)
        at android.view.View.performClick(View.java:7441)
        at android.view.View.performClickInternal(View.java:7418)
        at android.view.View.access$3700(View.java:835)
        at android.view.View$PerformClick.run(View.java:28676)
        at android.os.Handler.handleCallback(Handler.java:938)
        at android.os.Handler.dispatchMessage(Handler.java:99)
        at android.os.Looper.loopOnce(Looper.java:201)
        at android.os.Looper.loop(Looper.java:288)
        at android.app.ActivityThread.main(ActivityThread.java:7842)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1003)

build.gradle

plugins {
    id 'com.android.application'
    id 'kotlin-android'
    id 'kotlin-kapt'
    id 'androidx.navigation.safeargs.kotlin'
    id 'dagger.hilt.android.plugin'
    id 'kotlin-parcelize'
}

android {
    compileSdk 31

    defaultConfig {
        applicationId "com.example.todo"
        minSdk 24
        targetSdk 31
        versionCode 1
        versionName "1.0"

        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
    }

    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 {
        dataBinding true
        viewBinding true
    }
}

dependencies {
    implementation 'androidx.legacy:legacy-support-v4:1.0.0'
    def nav_version = "2.3.5"
    def room_version = "2.3.0"
    def lifecycle_version = "2.4.0"

    implementation 'androidx.core:core-ktx:1.7.0'
    implementation 'androidx.appcompat:appcompat:1.3.1'
    implementation 'com.google.android.material:material:1.4.0'
    implementation 'androidx.constraintlayout:constraintlayout:2.1.1'
    testImplementation 'junit:junit:'
    androidTestImplementation 'androidx.test.ext:junit:1.1.3'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'

    //Navigation component
    implementation "androidx.navigation:navigation-fragment-ktx:$nav_version"
    implementation "androidx.navigation:navigation-ui-ktx:$nav_version"

    //Room
    implementation "androidx.room:room-runtime:$room_version"
    annotationProcessor "androidx.room:room-compiler:$room_version"

    // Lifecycle
    implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:$lifecycle_version"
    implementation "androidx.lifecycle:lifecycle-livedata-ktx:$lifecycle_version"

    //Kotlin coroutines
    implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.5.0'

    //RecyclerView
    implementation 'jp.wasabeef:recyclerview-animators:4.0.2'

    //Hilt DI
    implementation "com.google.dagger:hilt-android:2.38.1"
    kapt "com.google.dagger:hilt-compiler:2.38.1"

}

ToDoData.kt

@Entity(tableName = "todo_table")
@Parcelize
data class ToDoData(
    @PrimaryKey(autoGenerate = true)
    var id: Int,
    var title: String,
    var description: String,
    var priority: Priority
) : Parcelable

ToDoDatabase.kt

@Database(entities = [ToDoData::class], version = 1, exportSchema = false)
@TypeConverters(Converter::class)
abstract class ToDoDatabase : RoomDatabase() {

    abstract fun toDoDao(): ToDoDao

}

ToDoViewModel.kt

@HiltViewModel
class ToDoViewModel @Inject constructor(
    private val repository: ToDoRepository
) : ViewModel() {

    private val getAllData: LiveData<List<ToDoData>> = repository.getAllData

    fun insertData(toDoData: ToDoData) {
        viewModelScope.launch(Dispatchers.IO) {
            repository.insertData(toDoData)
        }
    }
}

AppModule.kt

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

    @Singleton
    @Provides
    fun provideToDoDatabase(
        @ApplicationContext app: Context
    ) = Room.databaseBuilder(
        app,
        ToDoDatabase::class.java,
        "todo_database"
    )
        .fallbackToDestructiveMigration()
        .build()

    @Singleton
    @Provides
    fun provideTodoDao(db: ToDoDatabase) = db.toDoDao()

}

AddFragment.kt

下面是我调用的函数,用于从 AddFragment

插入数据
    private val viewModel: ToDoViewModel by viewModels()


private fun insertDataToDo() {
        val title = binding.titleEt.text.toString()
        val priority = binding.spinnerPriorities.selectedItem.toString()
        val description = binding.descriptionEt.text.toString()

        val validation = verifyDataFromUser(title, description)
        if (validation) {
            val data = ToDoData(
                0,
                title,
                description,
                parsePriority(priority)
            )
            viewModel.insertData(data)
            Toast.makeText(requireContext(), "Successfully Added!", Toast.LENGTH_SHORT).show()

            findNavController().navigate(R.id.action_addFragment_to_listFragment)
        } else
            Toast.makeText(requireContext(), "Please fill out all fields", Toast.LENGTH_SHORT)
                .show()


    }

    private fun verifyDataFromUser(title: String, description: String): Boolean {
        return if (TextUtils.isEmpty(title) || TextUtils.isEmpty(description)) {
            false
        } else !(title.isEmpty() || description.isEmpty())
    }

    private fun parsePriority(priority: String): Priority {
        return when (priority) {
            "High Priority" -> Priority.HIGH
            "Medium Priority" -> Priority.MEDIUM
            "Low Priority" -> Priority.LOW
            else -> Priority.LOW
        }
    }

我已经在这里看到了一些相同问题的问题,但它对我不起作用,所以我想知道问题出在哪里

最佳答案

我遇到了和你完全一样的问题,经过半天的尝试重写和删除代码 fragment ,最终我的问题通过将 annotationProcessor 更改为 kapt 解决了 build.gradle 文件。

// Hilt, Dependency injection
def hilt_version = "2.38.1"
implementation "com.google.dagger:hilt-android:$hilt_version"
annotationProcessor "com.google.dagger:hilt-compiler:$hilt_version"

// Room database
def room_version = "2.4.2"
implementation "androidx.room:room-runtime:$room_version"
annotationProcessor "androidx.room:room-compiler:$room_version"

更改和修复后:

// Hilt, Dependency injection
def hilt_version = "2.38.1"
implementation "com.google.dagger:hilt-android:$hilt_version"
kapt "com.google.dagger:hilt-compiler:$hilt_version"

// Room database
def room_version = "2.4.2"
implementation "androidx.room:room-runtime:$room_version"
kapt "androidx.room:room-compiler:$room_version"

鉴于控制台上打印的错误文本,我认为这根本不是问题!

关于android - 找不到实现(房间),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69955515/

相关文章:

android - 我应该为 sqlite 中的每个数据库操作打开和关闭数据库吗?

android - 单击 onCLickListener 按钮调用另一个模块

android - 如何 VACUUM RoomDatabase?

java - 如何打印 Room 数据库中的内部查询?

android - 我可以对不同的对象类型使用一个 TypeConverter 吗?

java - 显示 Android 上的所有广播事件

android - 挂断时拦截拨出电话

android - 与 android 支持库的依赖关系不适用于使用 Androidx 的项目

java - 为什么 Kotlin 不能为这个具有可为空值类型的 HashMap 推断类型?

java - 将字符串发送到服务器,不带反斜杠