【问题标题】:Prepopulating Room Database with Hilt使用 Hilt 预填充房间数据库
【发布时间】:2021-09-03 12:30:48
【问题描述】:

我正在尝试使用 RoomDatabase.Callback() 方法使用数据预填充 Room 数据库,并且这样做也取得了成功。后来我尝试用 Hilt 做同样的事情,但不知道如何在 hilt 模块中提供数据库时添加回调。

这是数据库模块:

@Module
@InstallIn(ApplicationComponent::class)
object DatabaseModule {

    @Singleton
    @Provides
    fun provideDatabase(
        @ApplicationContext context: Context
    ): PersonDatabase {
        return Room.databaseBuilder(
            context,
            PersonDatabase::class.java,
            "person_database"
        ).build()

    }

    @Singleton
    @Provides
    fun provideDao(database: PersonDatabase) = database.personDao()

}

这是回调类:


class PersonCallback @Inject constructor(
    private val dao: PersonDao
) : RoomDatabase.Callback() {

    private val applicationScope = CoroutineScope(SupervisorJob())

    override fun onCreate(db: SupportSQLiteDatabase) {
        super.onCreate(db)
        applicationScope.launch(Dispatchers.IO) {
            populateDatabase()
        }
    }

    private suspend fun populateDatabase() {
        val person = Person("FirstName", "LastName", 20)
        dao.insertData(person)
    }
}

我尝试过使用数据库并提供这样的 dao,但它卡在一个循环中并且应用程序崩溃了。简而言之,错误说,以下方式是递归的,因此是不允许的


    @Singleton
    @Provides
    fun provideDatabase(
        @ApplicationContext context: Context
    ): PersonDatabase {
        return Room.databaseBuilder(
            context,
            PersonDatabase::class.java,
            "person_database"
        ).addCallback(
            PersonCallback(provideDatabase(context).personDao())
        ).build()

    }

然后,我关注了一个 SO 帖子并尝试复制它,即:

Pre-populating Room database with Hilt without creating an extra instance of the database

根据上述情况,应用程序再次崩溃,提供了一个巨大的错误,该错误引用了自动生成的类,并且没有任何东西使它更有意义

我尝试的另一种方法是将 dao 作为参数传递,但它再次崩溃并出现错误说它导致依赖循环,因为我也将 dao 作为构造函数参数传递给存储库。


    @Singleton
    @Provides
    fun provideDatabase(
        @ApplicationContext context: Context,
        personDao: PersonDao
    ): PersonDatabase {
        return Room.databaseBuilder(
            context,
            PersonDatabase::class.java,
            "person_database"
        ).addCallback(
            PersonCallback(personDao)
        ).build()

    }

在所有这些尝试之后,我无法弄清楚我应该如何将 dao 传递给回调类并使其工作。我要求提出一些方法来实现这一点,或者任何替代方案也将不胜感激。

【问题讨论】:

    标签: java android kotlin android-room


    【解决方案1】:

    根据您在问题中添加的链接,您可以找到解决方案,只需编辑提供 PersonDatabase 的第一个方法

    @Singleton
    @Provides
    fun provideDatabase(
        @ApplicationContext context: Context,
        provider: Provider<PersonDao>
    ): PersonDatabase {
        return Room.databaseBuilder(
            context,
            PersonDatabase::class.java,
            "person_database"
        ).addCallback(
            PersonCallback(provider)
        ).build()
    
    }
    

    然后你的回调类为 PersonDao 提供提供者,只需为你的类编辑

    class PersonCallback (
    private val provider: Provider<PersonDao>
      ) : RoomDatabase.Callback() {
    
    private val applicationScope = CoroutineScope(SupervisorJob())
    
    override fun onCreate(db: SupportSQLiteDatabase) {
        super.onCreate(db)
        applicationScope.launch(Dispatchers.IO) {
            populateDatabase()
        }
    }
    
    private suspend fun populateDatabase() {
        val person = Person("FirstName", "LastName", 20)
        provider.get().insertData(person)
    }
    }
    

    我试试这段代码对我来说很好用

    【讨论】:

      猜你喜欢
      • 2023-03-11
      • 2021-10-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-10-22
      • 2021-12-28
      • 1970-01-01
      相关资源
      最近更新 更多