大家好!我是 Room 的初学者,我需要在第一次启动应用程序时使用启动数据创建数据库,然后修改应用程序中的数据并在第二次启动应用程序时使用修改后的数据。
我有这个代码
companion object {
@Volatile
private var INSTANCE: AppDatabase? = null
fun getDatabase(context: Context): AppDatabase {
return INSTANCE ?: synchronized(this) {
val instance = Room.databaseBuilder(
context.applicationContext,
AppDatabase::class.java,
"app_database.db",
)
.createFromAsset("database/01-01-2024.db")
.build()
INSTANCE = instance
instance
}
}
它成功创建了预填充的数据库,我可以在应用程序的下一个屏幕中修改数据。但是,当我关闭应用程序并第二次打开数据库时,修改后的数据将使用预填充的数据库重写。
如何仅当 BD 不存在时才使用预填充数据库?
附注我正在观看文档,但没有帮助。
根据您提供的代码,预填充的数据库应该在应用程序首次运行时将预填充的数据库从资产复制到标准数据库位置,后续运行应该看到数据库存在,然后不再重做副本。
这个过程是这样的:-
因此,您的问题是更改未应用于数据库,或者数据库正在被删除。
无法确定哪种情况导致您遇到问题。但是,也许可以考虑以下演示,它修改了您提供的可用于调试和确定问题的代码:-
首先是修改后的代码(参见注释),包括对包含单个@Dao
接口检索的
AppDatabase抽象类的猜测:-
@Database(entities = [TheTable::class], exportSchema = false, version = 1)
abstract class AppDatabase: RoomDatabase() {
abstract fun getAllDAOs(): AllDAOs
companion object {
@Volatile
private var INSTANCE: AppDatabase? = null
fun getDatabase(context: Context): AppDatabase {
/* Amended to inspect the database prior to acess it via Room */
preDBAccess(context)
return INSTANCE ?: synchronized(this) {
val instance = Room.databaseBuilder(
context.applicationContext,
AppDatabase::class.java,
"app_database.db",
)
/* Amended to invoke the PrePackagedDatabaseCallback (just to log when prepackaged database is used) */
.createFromAsset("database/01-01-2024.db", prePackagedDatabaseCallback)
/* Amended to invoke the standard callbacks (OnCreate,OnOpen,OnDestMig) IF INVOKED */
.addCallback(cb)
/* Amended to allow running on the main thread for brevity */
.allowMainThreadQueries()
.build()
INSTANCE = instance
instance
}
}
val cb = object: Callback(){
override fun onCreate(db: SupportSQLiteDatabase) {
super.onCreate(db)
Log.d(TAG+"ONCRT","OnCreate Callback invoked!.")
showDBInfo(db)
}
override fun onOpen(db: SupportSQLiteDatabase) {
super.onOpen(db)
Log.d(TAG+"ONOPN","OnOpen Callback invoked!.")
showDBInfo(db)
}
override fun onDestructiveMigration(db: SupportSQLiteDatabase) {
super.onDestructiveMigration(db)
Log.d(TAG+"ONDM","OnDestructiveMigration invoked!.")
showDBInfo(db)
}
}
val prePackagedDatabaseCallback = object:PrepackagedDatabaseCallback(){
override fun onOpenPrepackagedDatabase(db: SupportSQLiteDatabase) {
super.onOpenPrepackagedDatabase(db)
Log.d(TAG + "_PPDC","PrePackagedDatabase Callback invoked!.")
showDBInfo(db)
}
}
fun showDBInfo(db: SupportSQLiteDatabase) {
var csr = db.query("SELECT * FROM sqlite_master")
DatabaseUtils.dumpCursor(csr)
csr = db.query("SELECT * FROM thetable")
DatabaseUtils.dumpCursor(csr)
csr.close()
}
fun preDBAccess(context: Context) {
Log.d(TAG+"PDBA","Pre Database Access processing initiated!.")
val dbFileExists = context.getDatabasePath("app_database.db").exists()
if (!dbFileExists) {
Log.d(TAG+"PDBA","Database file app_database.db does not exist! (should be copied from asset)")
} else {
Log.d(TAG+"PDBA","Database file app_database.db exists!.")
val db = SQLiteDatabase.openDatabase(context.getDatabasePath("app_database.db").path,null,0)
Log.d(TAG+"PDBAV","Database version is ${db.version}")
var csr = db.rawQuery("SELECT * FROM sqlite_master",null)
DatabaseUtils.dumpCursor(csr)
csr = db.rawQuery("SELECT * FROM thetable",null)
DatabaseUtils.dumpCursor(csr)
csr.close()
db.close()
}
}
}
}
用于演示的其他 Room 类包括:-
const val TAG: String ="DBINFO"
@Entity
data class TheTable(
@PrimaryKey
var id: Long?=null,
var a_column: String
)
@Dao
interface AllDAOs {
@Insert(onConflict = OnConflictStrategy.IGNORE)
fun insert(theTable: TheTable): Long
@Query("SELECT * FROM thetable")
fun getAllFromTheTable(): List<TheTable>
}
实际演示一些活动代码(为了简洁起见,使用主线程):-
class MainActivity : AppCompatActivity() {
lateinit var db: AppDatabase
lateinit var dao: AllDAOs
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
db = AppDatabase.getDatabase(this)
dao = db.getAllDAOs()
/* NOTE database has NOT been accessed yet so no copy undertaken */
for (tt in dao.getAllFromTheTable()) {
Log.d(TAG+"ADBA","TT Row ID=${tt.id} a_column=${tt.a_column}")
}
for (i in 1..10) {
dao.insert(TheTable(null,"INSRT_${i} at ${System.currentTimeMillis()}"))
}
for (tt in dao.getAllFromTheTable()) {
Log.d(TAG+"AINSRT","TT Row ID=${tt.id} a_column=${tt.a_column}")
}
}
}
当应用程序运行时,这将是:-