我正在使用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。很明显这应该是可能的,因为谷歌正在将Room和Dagger推到一起,这可能是一个非常常见的用例。
我尝试将DAO作为provideDB()
的构造函数参数提供,但这会创建循环依赖
我尝试将RoomDatabase初始化为伴侣对象。然后,我可以调用可以访问DAO的Room.builder
方法,而不是在provideDB()
方法中使用getInstance()
格式。但是这种方式我遇到了一个错误的递归调用getWriteableDatabase()
。
我知道我可以使用像db.execSQL()
这样的东西,但是当我使用Room时,这样做真是太可惜了。
有没有更好的方法让我失踪?我使用Kotlin,但欢迎使用Java示例。 :)
答案 0 :(得分:0)
您可以创建最终的单元素数组。
@AppScope
@Provides
public AppDatabase appDatabase(@ApplicationContext Context appContext, AppExecutors executors) {
final AppDatabase[] databases = new AppDatabase[1];
databases[0] = Room.databaseBuilder(appContext, AppDatabase.class, AppDatabase.DATABASE_NAME)
.fallbackToDestructiveMigration()
.addCallback(new RoomDatabase.Callback() {
@Override
public void onCreate(@NonNull SupportSQLiteDatabase db) {
super.onCreate(db);
executors.diskIO().execute(() -> {
databases[0].populateDatabaseOnCreate();
});
}
}).build();
return databases[0];
}
答案 1 :(得分:0)
我已经这样管理了它:
@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()
}
但是请记住,您需要从数据库中进行虚假读取,以启动db并调用onCreate()。未创建db时,请勿在第一次交互时写入db,因为这会创建竞争条件,并且您在创建时的写入不会生效。
答案 2 :(得分:-1)
您可以在java中执行此操作
AppDatabase appDatabase = null;
AppDatabase finalAppDatabase = appDatabase;
appDatabase = Room.databaseBuilder(MyApplication.getApplication(),
AppDatabase.class, Constants.DATABASE_NAME).
addCallback(new RoomDatabase.Callback() {
@Override
public void onCreate(@NonNull SupportSQLiteDatabase db) {
super.onCreate(db);
//check for null
finalAppDatabase.yourDao();
}
}).
build();
return appDatabase;