当前位置: 首页 > 知识库问答 >
问题:

抽象房间数据库实现未找到匕首柄

微生智刚
2023-03-14

我是Android开发新手,需要为大学建立我的第一个项目。大学用的是旧版本的XML和Java,但是我想学Compose,所以我学了Kotlin。

现在,在设置好一切之后,我试图使用hiltViewModel()方法将视图模型注入到可组合函数中,但我得到了一个错误。我看了这个教程:https://www.youtube.com/watch?v=A7CGcFjQQtQ

在让这个工作之后。现在它说找不到数据库类实现,但我希望 Dagger Hilt 会产生这个?对于房间数据库

这是基本代码:

依赖性:

构建梯度:

buildscript {
    ext {
        compose_version = '1.0.0'
    }
    repositories {
        google()
        mavenCentral()
    }
    dependencies {
        classpath "com.android.tools.build:gradle:7.0.0"
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.5.10"

        //->Adding the Dagger Hilt class path here as suggested:
        classpath 'com.google.dagger:hilt-android-gradle-plugin:2.38.1'

        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
    }
}

app/build.gradle:

plugins {
    id 'com.android.application'
    id 'kotlin-android'
    //->Adding Kotlin annotation processing plugin and the dagger hilt plugin:
    id 'kotlin-kapt'
    id 'dagger.hilt.android.plugin'
}

android {
    compileSdk 31

    defaultConfig {
        applicationId "ac.gre.mxpenseresit"
        minSdk 21
        targetSdk 31
        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'
        useIR = true
    }
    buildFeatures {
        compose true
    }
    composeOptions {
        kotlinCompilerExtensionVersion compose_version
        kotlinCompilerVersion '1.5.10'
    }
    packagingOptions {
        resources {
            excludes += '/META-INF/{AL2.0,LGPL2.1}'
        }
    }
}

dependencies {

    implementation 'androidx.core:core-ktx:1.8.0'
    implementation 'androidx.appcompat:appcompat:1.4.2'
    implementation 'com.google.android.material:material:1.6.1'
    implementation "androidx.compose.ui:ui:$compose_version"
    implementation "androidx.compose.material:material:$compose_version"
    implementation "androidx.compose.ui:ui-tooling-preview:$compose_version"
    implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.4.1'
    implementation 'androidx.activity:activity-compose:1.4.0'
    testImplementation 'junit:junit:4.+'
    androidTestImplementation 'androidx.test.ext:junit:1.1.3'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
    androidTestImplementation "androidx.compose.ui:ui-test-junit4:$compose_version"
    debugImplementation "androidx.compose.ui:ui-tooling:$compose_version"

    //This version for navigation is hard coded, probably will need to update later, but should be fine for assignment
    implementation("androidx.navigation:navigation-compose:2.4.2")

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

    //Coroutine dependency:
    implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.9"
    implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.9'

    //->Dagger Hilt Dependency for DI copied from official docs:
    implementation "com.google.dagger:hilt-android:2.38.1"
    kapt "com.google.dagger:hilt-compiler:2.38.1"

}

import android.app.application import dagger.hilt.android.HiltAndroidApp

/**
 * Adding the Hilt Android App dependency for the Application class
 */
@HiltAndroidApp
class MExpenseApp : Application() {

}

主要的

@AndroidEntryPoint
class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            MXPenseResitTheme {
                // A surface container using the 'background' color from the theme
                Surface(color = MaterialTheme.colors.background) {
                   App(modifier = Modifier)
                }
            }
        }
    }
}

主模块:

**
 * Setup dependencies:
 */
@Module
@InstallIn(ActivityComponent::class)
object MainModule {

    @Provides
    @Singleton
    fun provideDb(application: Application): MExpenseDb {
        return Room
            .databaseBuilder(
                application,
                MExpenseDb::class.java,
                "MExpenseDb"
            ).build()
    }

    /**
     * We are type hinting to the Interface so we can change implementations
     */
    @Provides
    @Singleton
    fun provideTripRepository(mExpenseDb: MExpenseDb): TripRepositoryContract {
        return TripRepository(mExpenseDb.tripDao)
    }

}

查看模型:

@HiltViewModel
class TripListVm @Inject constructor(
    private val tripRepository: TripRepository
) : ViewModel() {

    /**
     * @var trips
     * Get all trips
     */
    val trips = tripRepository.getTrips()
    val testStr: String = "Test String!"
    
}

可堆肥:

@Composable
fun TripList(
    navController: NavHostController,
    modifier: Modifier = Modifier,
    tripListVm: TripListVm = hiltViewModel()
) {
    
    Text(text = "Trip List")
    TripListItem(
        name = "Trip Name",
        date = "16/04/1885",
        amount = 46.66,
        modifier = modifier
    )
}

结果:

我也收到一个错误:[匕首/丢失绑定]异常。ac.gre.mxpenseresit.data.repository.TripRepository 不能在没有@Inject构造函数或@Provides注释方法的情况下提供

以下是数据层的代码:

数据库类:

@Database(
    entities = [
        Trip::class,
        Expense::class,
    ],
    version = 1
)
abstract class MExpenseDb : RoomDatabase() {

    abstract val tripDao: TripDao

}

刀:

@Dao
interface TripDao {

    /**
     * Gets all trips
     */
    @Query("SELECT * FROM Trip")
    fun getTrips(): Flow<List<Trip>>

    /**
     * Gets trips based on a named search,
     * This functionality can be extended later
     */
    @Query("SELECT * FROM Trip t WHERE t.name LIKE :name")
    suspend fun getTripsBySearchName(name: String)

    /**
     * Gets trip by Id
     */
    @Query("SELECT * FROM Trip WHERE Trip.id = :id")
    suspend fun getTripById(id: Long)

    /**
     *
     */
    @Insert(onConflict = OnConflictStrategy.REPLACE)
    suspend fun saveTrip(trip: Trip): Long


    @Delete
    suspend fun deleteTrip(trip: Trip)

}

行程存储库合约(接口):

interface TripRepositoryContract {

    fun getTrips(): Flow<List<Trip>>
    suspend fun getTripById(id: Long): Trip?
    suspend fun getTripsBySearchName(keyword: String): List<Trip>
    suspend fun saveTripLocal(trip: Trip)
    suspend fun saveTripRemote(trip: Trip)
    suspend fun deleteTrip(trip: Trip)

}

行程存储库实现:

class TripRepository (val tripDao: TripDao) : TripRepositoryContract {

    override fun getTrips(): Flow<List<Trip>> {
        return tripDao.getTrips();
    }

    override suspend fun getTripById(id: Long): Trip? {
        TODO("Not yet implemented")
    }

    override suspend fun getTripsBySearchName(keyword: String): List<Trip> {
        TODO("Not yet implemented")
    }

    override suspend fun saveTripLocal(trip: Trip) {
        TODO("Not yet implemented")
    }

    override suspend fun saveTripRemote(trip: Trip) {
        TODO("Not yet implemented")
    }

    override suspend fun deleteTrip(trip: Trip) {
        TODO("Not yet implemented")
    }
}

现在 hiltViewModel() 方法工作正常,但我没有得到一个MExpenseDb_impl类

我看了一下这个堆栈溢出问题:Android room persistent:app database _ Impl不存在

它说要使用保留的依赖关系,我已经有了同样的注释处理,所以我不确定这是否是一个问题

网上所有的教程要么太长

共有1个答案

叶声
2023-03-14

要提供TripRepository,您需要创建一个带有Hilt's Bind函数的类。例子:

@Module
@InstallIn(SingletonComponent::class)
interface RepositoryModule {    
    @Binds
    @Singleton
    fun bindTripRepository(
        repository: TripRepository // here the class
    ): TripRepositoryContract // here the interface that the class implements
}

还需要修改TripRepository。您必须添加@Inject构造函数()(即使您的类不使用任何依赖项),以便Hill可以创建该类
在您的情况下,它将如下所示:

class TripRepository @Inject constructor(
    val tripDao: TripDao
) : TripRepositoryContract {
    // ...
}

最后一个更改是在主模块中:

@Module
@InstallIn(SingletonComponent::class)
object MainModule {
    // providing the db implementation normally
    @Provides
    @Singleton
    fun provideDb(application: Application): MExpenseDb {
        return Room.databaseBuilder(
            application,
            MExpenseDb::class.java,
            "MExpenseDb"
        ).build()
    }

    // providing your dao interface to be injected into TripRepository
    @Provides
    @Singleton
    fun provideTripDao(
        mExpenseDb: MExpenseDb
    ): TripDao = mExpenseDb.tripDao
}

请注意,我在Hilt的模块中从ActivityComponent更改为SingletonComponent,在这两种情况下,我们都希望它们在整个项目中是单例的,而不仅仅是为活动创建的组件(也可以是单例)。
请在此处查看组件生命周期。
我还建议在您的项目中升级Hilt版本,因为您使用的是非常旧的版本。最新版本是2.42

我认为这个视频可以帮助你更好地理解关于Hilt的一些事情。还有一个项目的存储库,它将Hilt和room结合在一起,对你的参考很有用。

重要编辑:
TripListVm中,您使用的是私有val tripRepository:TripRepostory(您实现TripRepocitoryContract的类),不建议直接注入实现类,相反,您应该注入接口(TripReppositoryContrract),并让希尔特负责提供它的实现。因为这就是我们在RepositoryModule中教希尔特做的
因此,为了使其更理想,TripListVm将如下所示:

@HiltViewModel
class TripListVm @Inject constructor(
    private val tripRepositoryContract: TripRepositoryContract
) : ViewModel() {
    // ...
}
 类似资料:
  • 我环顾了这里和其他网站,但我想不出解决办法。 一切正常,直到我初始化中的。 我一直在犯这个错误 我有这个格里德尔 当我添加插件和时,它说它们找不到。 但那给了我这些错误 在数据库文件中,我做了如下操作: 并将所有东西连接到RoomViewModel(我也为它创建了一个工厂) 这是我做的 我认为上下文有问题,但我真的不知道。还在学习。。。 请帮帮忙

  • 这是一个自我回答的问题,我想在早些时候问这个问题,因为我的项目中存在代表曝光问题,但经过几个小时的研究,最终还是解决了这个问题。与其保持沉默,我想这可能会对将来的人有所帮助。本教程演示了如何创建Room数据库并在活动/片段中使用它。这里给出的示例用例是查询数据库的大小并更新片段中的视图。 注意:下面的代码中有一些 Dagger-Hilt 依赖项注入,但如果您手动执行自己的依赖项注入,则应应用相同的

  • 当我试图构建我的应用程序时,我遇到了以下编译错误: 持久性模块在Android设置中是独立的。 建筑格拉德尔 ext.androidXRoom=“2.1.0-alpha02” 我试着把kotlin版本,room版本,改回AndroidArch room,但没用。我还尝试了清理项目和使Android Studio的缓存失效。但它不起作用。 编辑:AppDatabase源

  • 错误:查询有问题:[SQLITE_ERROR]SQL错误或缺少数据库(没有这样的表:任务) 显示了这个错误,我怎么可能修复它? 我正在学习这个教程

  • 并且我发现了基于数据库版本4的可能场景的迁移varargs。 我的问题是,假设我使用的是db v1的Room,当我的应用程序到达db v10时,我将不得不编写多少迁移方法? 在sqlite中,我们在中获得已安装应用程序的当前db版本,我们只需通过开关大小写而不使用break语句,以便满足所有db升级。

  • 我是新来的和我试图我的得到一个从它。我试图这样做的它与这是id但问题是我不知道如何返回目标从。 这就是<代码>刀 这是Repository类