[英]RoomDatabase onCreate called twice
調用onCreate
時,我正在使用RoomDatabase.Callback
填充數據庫。 根據文檔,此方法僅應在首次創建數據庫時調用一次 。
首次創建數據庫時調用。 創建所有表后將調用此方法。
但是由於某種原因,它被兩次調用(有時超過兩次)。 如果在第二次調用中替換了數據,這並不是什么大問題,但是由於每個調用都使用單獨的輸入調用啟動了一個新線程,因此它正在創建重復數據。
這是有問題的數據庫。
@Database(entities = [FTSPlaceholder::class], version = 1)
abstract class DirectoryDatabase : RoomDatabase() {
companion object {
const val NAME = "directory_database"
@Volatile private var INSTANCE: DirectoryDatabase? = null
fun getInstance(context: Context): DirectoryDatabase = INSTANCE ?: synchronized(this) {
INSTANCE ?: buildDatabase(context).also { INSTANCE = it }
}
private fun buildDatabase(context: Context): DirectoryDatabase =
Room.databaseBuilder(context.applicationContext, DirectoryDatabase::class.java, NAME)
.addCallback(FTSCallback()).build()
}
fun addCallback(callback: Callback) {
if (mCallbacks == null) mCallbacks = ArrayList()
mCallbacks?.add(callback)
}
abstract fun departmentDao(): DepartmentDao
abstract fun employeeDao(): EmployeeDao
private class FTSCallback : Callback() {
companion object {
private const val CREATE_TABLE_DEPARTMENTS =
"CREATE VIRTUAL TABLE IF NOT EXISTS `departments` " +
"USING FTS4(`code` TEXT NOT NULL, `title` TEXT NOT NULL, " +
"`location` TEXT NOT NULL, `phone` TEXT, `fax` TEXT, PRIMARY KEY(`code`))"
private const val CREATE_TABLE_PERSONNEL =
"CREATE VIRTUAL TABLE IF NOT EXISTS `personnel` " +
"USING FTS4(`familyName` TEXT NOT NULL, `givenName` TEXT NOT NULL, " +
"`middleName` TEXT, `title` TEXT NOT NULL, `location` TEXT NOT NULL, " +
"`room` TEXT NOT NULL, `phone1` TEXT NOT NULL, `phone2` TEXT NOT NULL, " +
"`email` TEXT NOT NULL, `fax` TEXT, `department` TEXT NOT NULL, " +
"`school` TEXT, PRIMARY KEY(`familyName`, `givenName`, `title`))"
}
override fun onCreate(db: SupportSQLiteDatabase) {
db.execSQL(CREATE_TABLE_DEPARTMENTS)
db.execSQL(CREATE_TABLE_PERSONNEL)
}
}
}
為了增加對FTS的支持,我在做一些奇怪的事情,但這不應該導致onCreate()
被調用兩次。 特別是考慮到我在另一個數據庫中執行相同的操作,這不會導致相同的問題。
@Database(entities = [Area::class], version = 1)
abstract class MapDatabase : RoomDatabase() {
companion object {
const val NAME = "map_database"
@Volatile private var INSTANCE: MapDatabase? = null
fun getInstance(context: Context): MapDatabase = INSTANCE ?: synchronized(this) {
INSTANCE ?: buildDatabase(context).also { INSTANCE = it }
}
private fun buildDatabase(context: Context): MapDatabase =
Room.databaseBuilder(context.applicationContext, MapDatabase::class.java, NAME)
.addCallback(FTSCallback()).build()
}
fun addCallback(callback: Callback) {
if (mCallbacks == null) mCallbacks = ArrayList()
mCallbacks?.add(callback)
}
abstract fun placeDao(): PlaceDao
abstract fun areaDao(): AreaDao
private class FTSCallback : Callback() {
companion object {
private const val CREATE_TABLE_PLACES =
"CREATE VIRTUAL TABLE IF NOT EXISTS `places` " +
"USING FTS4(`id` INTEGER NOT NULL, `title` TEXT NOT NULL, " +
"`subtitle` TEXT, `description` TEXT, `latitude` REAL NOT NULL, " +
"`longitude` REAL NOT NULL, `type` INTEGER NOT NULL, " +
"`parent` INTEGER, PRIMARY KEY(`id`))"
}
override fun onCreate(db: SupportSQLiteDatabase) {
db.execSQL(CREATE_TABLE_PLACES)
}
}
}
我在單獨的存儲庫類中將回調添加到數據庫。
class DirectoryRepository(application: Application) {
private val database = DirectoryDatabase.getInstance(application)
init {
database.addCallback(object : RoomDatabase.Callback() {
// This method is being called twice
override fun onCreate(db: SupportSQLiteDatabase) {
refresh()
}
}
}
// Code omitted for brevity
}
我無法弄清楚為什么會這樣,尤其是考慮到它僅發生在我的兩個(非常相似)實現中之一。
class DirectoryRepository
有可能多次實例化,並且在每次init
調用時都會添加回調。
除此之外,您應該使用RoomDatabase
類的構建器提供的addCallback()
添加回調。
否則,您可能會面臨相反的問題,即根本不會觸發回調。 如果在<database-class>_Impl.createOpenHelper(...)
方法中創建的SupportSQLiteOpenHelper
之后手動添加回調,則會發生這種情況。
即使在同步塊中,也應檢查instance == null
。
fun getInstance(context: Context): DirectoryDatabase {
return INSTANCE ?: synchronized(this) {
if(INSTANCE != null) {
return@synchronized database
}
val database = Room.databaseBuilder(context.applicationContext,
DirectoryDatabase::class.java, NAME)
.addCallback(FTSCallback())
.build()
INSTANCE = database
return@synchronized database
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.