Android 房间预填充 SQL 数据库并持久更新
Android Room Prepopulate SQL database and update with persistence
我正在尝试使用 Kotlin 来:
- 从现有 SQL 数据库中预填充我的应用程序中的房间数据库。
- 允许用户更新数据。
- 让更新的数据只保留当前版本。
- 让新版本清除旧数据并将其替换为新发布的 SQL 数据库。
这是我目前所做的:
我使用 createFromAsset
方法通过 fallbackToDestructiveMigration()
调用预填充数据库,如下所示:
@Database(entities = [MCData::class], version = 1, exportSchema = false)
abstract class MyRoom : RoomDatabase() {
abstract val myDao: MyDao
companion object {
@Volatile
private var INSTANCE: MyRoom? = null
fun getInstance(context: Context): MyRoom {
synchronized(this) {
var instance = INSTANCE
if (instance == null) {
instance = Room.databaseBuilder(
context.applicationContext,
MyRoom::class.java,
"mcdata.db")
.createFromAsset("mydata.db")
.fallbackToDestructiveMigration()
.build()
INSTANCE = instance
}
return instance
}
}
}
这是预填充数据并让用户更改它,但是当应用程序重新启动时,初始填充后的数据更新会丢失。我对这种行为感到困惑,因为看起来代码正在使用 fallbackToDestructiveMigration()
刷新数据,即使架构没有更改(用户只能更改两个现有列的值)。
如果我删除 fallbackToDestructiveMigration()
方法,那么在初始预填充后用户的更新会持续存在,但是当我使用新数据重新安装应用程序时,数据库不会得到更新。
有没有办法让数据(包括编辑)保留在当前版本中,但在安装新版本时被新的预填充 SQL 数据库替换?
我最终创建了两个构建器函数:
- 第一个在第一次安装或更新软件时调用,它从资产数据库中读取。
- 第二个在其他时间调用,它从本地创建的数据库中读取,因此用户对版本的小调整仍然存在。
@Database(entities = [MCData::class,FBData::class,WhereAmIdata::class], version = 1, exportSchema = false)
abstract class MyRoom : RoomDatabase() {
abstract val myDao: MyDao
companion object {
@Volatile // with volatile, changes immediately become visible to all threads
private var INSTANCE: MyRoom? = null
// this instantiaion is called the first time the software is updated
fun getInstanceAfterSoftwareUpdate(context: Context): MyRoom {
synchronized(this) {
var instance = INSTANCE
if (instance == null) {
instance = Room.databaseBuilder(
context.applicationContext,
MyRoom::class.java,
"mcdata")
.createFromAsset("mydata.db")
.fallbackToDestructiveMigration()
.build()
INSTANCE = instance
}
return instance
}
}
fun getInstance(context: Context): MyRoom {
synchronized(this) {
var instance = INSTANCE
if (instance == null) {
Log.i("MyRoom", "reading locally")
instance = Room.databaseBuilder(
context.applicationContext,
MyRoom:: class.java,
"mcdata"
)
.fallbackToDestructiveMigration()
.build()
INSTANCE = instance
}
return instance
}
}
}
}
我正在尝试使用 Kotlin 来:
- 从现有 SQL 数据库中预填充我的应用程序中的房间数据库。
- 允许用户更新数据。
- 让更新的数据只保留当前版本。
- 让新版本清除旧数据并将其替换为新发布的 SQL 数据库。
这是我目前所做的:
我使用 createFromAsset
方法通过 fallbackToDestructiveMigration()
调用预填充数据库,如下所示:
@Database(entities = [MCData::class], version = 1, exportSchema = false)
abstract class MyRoom : RoomDatabase() {
abstract val myDao: MyDao
companion object {
@Volatile
private var INSTANCE: MyRoom? = null
fun getInstance(context: Context): MyRoom {
synchronized(this) {
var instance = INSTANCE
if (instance == null) {
instance = Room.databaseBuilder(
context.applicationContext,
MyRoom::class.java,
"mcdata.db")
.createFromAsset("mydata.db")
.fallbackToDestructiveMigration()
.build()
INSTANCE = instance
}
return instance
}
}
}
这是预填充数据并让用户更改它,但是当应用程序重新启动时,初始填充后的数据更新会丢失。我对这种行为感到困惑,因为看起来代码正在使用 fallbackToDestructiveMigration()
刷新数据,即使架构没有更改(用户只能更改两个现有列的值)。
如果我删除 fallbackToDestructiveMigration()
方法,那么在初始预填充后用户的更新会持续存在,但是当我使用新数据重新安装应用程序时,数据库不会得到更新。
有没有办法让数据(包括编辑)保留在当前版本中,但在安装新版本时被新的预填充 SQL 数据库替换?
我最终创建了两个构建器函数:
- 第一个在第一次安装或更新软件时调用,它从资产数据库中读取。
- 第二个在其他时间调用,它从本地创建的数据库中读取,因此用户对版本的小调整仍然存在。
@Database(entities = [MCData::class,FBData::class,WhereAmIdata::class], version = 1, exportSchema = false)
abstract class MyRoom : RoomDatabase() {
abstract val myDao: MyDao
companion object {
@Volatile // with volatile, changes immediately become visible to all threads
private var INSTANCE: MyRoom? = null
// this instantiaion is called the first time the software is updated
fun getInstanceAfterSoftwareUpdate(context: Context): MyRoom {
synchronized(this) {
var instance = INSTANCE
if (instance == null) {
instance = Room.databaseBuilder(
context.applicationContext,
MyRoom::class.java,
"mcdata")
.createFromAsset("mydata.db")
.fallbackToDestructiveMigration()
.build()
INSTANCE = instance
}
return instance
}
}
fun getInstance(context: Context): MyRoom {
synchronized(this) {
var instance = INSTANCE
if (instance == null) {
Log.i("MyRoom", "reading locally")
instance = Room.databaseBuilder(
context.applicationContext,
MyRoom:: class.java,
"mcdata"
)
.fallbackToDestructiveMigration()
.build()
INSTANCE = instance
}
return instance
}
}
}
}