android - 通过 Dagger 2 提供 RoomDatabase 时实现 .addCallback() 的正确方法是什么?

标签 android kotlin dagger-2 android-room

我正在使用 Dagger 2 在我的应用中根据需要创建和共享我的 RoomDatabase。

我正在尝试实现 addCallback() 以便我可以覆盖数据库的 onCreate() 函数并使用它来插入我的初始数据库值。这就是我遇到问题的地方。

我觉得我必须忽略一些显而易见的事情,但我想不出一种优雅的方法。

RoomDatabase 类:

@Database(
        entities = [Station::class],
        version = 1,
        exportSchema = false
)
abstract class TrainDB : RoomDatabase() {

    abstract fun stationDao() : StationDao

} 

DAO:

@Dao
abstract class StationDao {

    @Insert(onConflict = OnConflictStrategy.REPLACE)
    abstract fun insert(stations: Station)

    @Query("SELECT * FROM station_table")
    abstract fun getAll() : LiveData<List<Station>>

}

Dagger 模块:

@Module
class DataModule {

    @Singleton
    @Provides
    fun provideDb(app: Application): TrainDB {
        var trainDB: TrainDB? = null
        trainDB = Room
                .databaseBuilder(app, TrainDB::class.java, "train.db")
                .allowMainThreadQueries()
                .fallbackToDestructiveMigration()
                .addCallback(object : RoomDatabase.Callback() {
                    override fun onCreate(db: SupportSQLiteDatabase) {
                        super.onCreate(db)

                        /*
                        WHAT GOES HERE?
                        */

                    }
                })
                .build()
        return trainDB
    }

    @Singleton
    @Provides
    fun providesStationDao(db: TrainDB) : StationDao = db.stationDao()

}

我希望能够在 onCreate() 回调中访问我的 DAO。很明显这应该是可能的,因为 Google 正在将 Room 和 Dagger 放在一起,这可能是一个非常常见的用例。

我尝试将 DAO 作为 provideDB() 的构造函数参数提供,但这会产生循环依赖

我尝试将我的 RoomDatabase 初始化为伴随对象。然后在我的 provideDB() 方法中使用 Room.builder 格式,我可以调用一个 getInstance() 方法来访问道。但是这样我遇到了递归调用 getWriteableDatabase() 的错误。

我知道我可以使用 db.execSQL() 之类的东西,但是当我使用 Room 时这样做似乎太可惜了。

我错过了更好的方法吗?我正在使用 Kotlin,但欢迎使用 Java 示例。 :)

最佳答案

我是这样管理的:

@Module
class DataModule {

lateinit var trainDB: TrainDB

@Singleton
@Provides
fun provideDb(app: Application): TrainDB {
    trainDB = Room
            .databaseBuilder(app, TrainDB::class.java, "train.db")
            .allowMainThreadQueries()
            .fallbackToDestructiveMigration()
            .addCallback(object : RoomDatabase.Callback() {
                override fun onCreate(db: SupportSQLiteDatabase) {
                    super.onCreate(db)

                    /*

                    trainDB.stationDao().insert(...)


                    */

                }
            })
            .build()
    return trainDB
}

@Singleton
@Provides
fun providesStationDao(db: TrainDB) : StationDao = db.stationDao()

}

但请记住,您需要从数据库中进行虚假读取以启动数据库并调用 onCreate()。当 db 尚未创建时,不要在第一次交互时写入 db,因为它会产生竞争条件,并且您的 on create 写入不会生效。

关于android - 通过 Dagger 2 提供 RoomDatabase 时实现 .addCallback() 的正确方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50520840/

相关文章:

android - Android的一个项目中是否可以有两个以上的包?

kotlin - Kotlin-Kotlin是否像Java中的基类一样包含Object类?

java - 通过意图传递 mutableList

numpy - 什么 kotlin 包提供了 numpy 功能?

android - 带有子组件和带有依赖组件的组件的 Dagger 2 问题

java - Dagger 2 多重绑定(bind)教程的@AutoAnnotation 不起作用。如何让它发挥作用?

android - 在Android应用中更改为横向模式时如何禁用广告?

java - 使用 RxJava CompositeSubscription 进行 Presenter 单元测试

android - Dagger 2.10 - 提供 AndroidInjector 注释

android - "Enable Device Admin"对话框不显示