android代码打开数据库,android – 如何正确关闭并重新打开Room数据库
您好我有2個(gè)應(yīng)用程序依賴于制作和恢復(fù)應(yīng)用程序數(shù)據(jù)庫(kù)的備份,只需將數(shù)據(jù)庫(kù)文件復(fù)制到SD卡中,然后很難確定如何在關(guān)閉它之后重新打開(kāi)Room Database單例以創(chuàng)建數(shù)據(jù)庫(kù)’副本.
構(gòu)建數(shù)據(jù)庫(kù):
@Database(version = 15, exportSchema = true, entities = [list of entities])
abstract class AppDatabase : RoomDatabase() {
//list of DAOs
companion object {
@Volatile private var INSTANCE: AppDatabase? = null
fun getInstance(context: Context): AppDatabase =
INSTANCE ?: synchronized(this) {
INSTANCE ?: buildDatabase(context).also {
INSTANCE = it
}
}
private fun buildDatabase(context: Context) =
Room.databaseBuilder(
context.applicationContext,
AppDatabase::class.java,
"Fazendao.sqlitedb"
)
.addMigrations(Migration1315)
.build()
}
}
關(guān)閉數(shù)據(jù)庫(kù):
fun closeDatabase() {
if(db.isOpen) {
db.openHelper.close()
}
}
使數(shù)據(jù)庫(kù)文件復(fù)制(在ViewModel中):
fun exportaBkpObservable(nome: String, auto: String, storage: File, database: File) {
disposable.clear()
setFlagsNull()
flagSubject.onNext(false)
disposable.add(
Observable.fromCallable {
repo.recordBkpName(nome)
}
.subscribeOn(Schedulers.io())
.flatMap {
return@flatMap try {
//closing the database
repo.closeDatabase()
Observable.just(
database.copyTo(File(storage, auto), true)
)
.flatMap {
val myDb = SQLiteDatabase.openOrCreateDatabase(it, null)
val ok = myDb.isDatabaseIntegrityOk
if(myDb.isOpen) myDb.close()
if(ok) {
Observable.just(ok)
} else {
Observable.error(Throwable("CORRUPTED DATABASE"))
}
}
} catch (t: Throwable) {
Observable.error(t)
}
}
.subscribe(
{},
{
errorFlag = "exportDB: " + it.message
errorSubject.onNext("exportDB: " + it.message)
},
{
//trying to reopen database
repo.openDatabase()
trueFlag = true
flagSubject.onNext(true)
}
)
)
}
repo是注入AppDatabase的存儲(chǔ)庫(kù),然后在ViewModelFactory中注入.
注射:
object MainInjection {
private fun providesIORepo(context: Context): IORepo {
return IORepo(AppDatabase.getInstance(context))
}
fun provideIOViewModelFactory(context: Context): IOViewModelFactory {
val data = providesIORepo(context)
return IOViewModelFactory(data)
}
}
在AppCompatActivity onCreate中:
val modelFactory = MainInjection.provideIOViewModelFactory(this)
viewModel = ViewModelProviders.of(this, modelFactory).get(IOViewModel::class.java)
重新打開(kāi)數(shù)據(jù)庫(kù):
fun openDatabase() {
if(!db.isOpen){
db.openHelper.writableDatabase
}
}
現(xiàn)在錯(cuò)誤消息:
試圖重新打開(kāi)數(shù)據(jù)庫(kù):
E/ROOM: Invalidation tracker is initialized twice :/.
因此當(dāng)我嘗試從另一個(gè)函數(shù)訪問(wèn)它時(shí)崩潰:
Cannot perform this operation because the connection pool has been closed.
關(guān)閉數(shù)據(jù)庫(kù)后,我有時(shí)也會(huì):
E/ROOM: Cannot run invalidation tracker. Is the db closed?
在這篇文章Incrementally migrate from SQLite to Room中,作者為每次訪問(wèn)它打開(kāi)和關(guān)閉數(shù)據(jù)庫(kù),所以我不明白為什么我的實(shí)現(xiàn)不起作用.
那我在哪里錯(cuò)了?有沒(méi)有辦法停用InvalidationTracker?
我是否應(yīng)該使用以下代碼關(guān)閉數(shù)據(jù)庫(kù)并在每次必須復(fù)制數(shù)據(jù)庫(kù)文件時(shí)清除Room實(shí)例.安全嗎?:
fun destroyInstance() {
if (INSTANCE?.isOpen == true) {
INSTANCE?.close()
}
INSTANCE = null
}
感謝您的關(guān)注.
解決方法:
好的,我開(kāi)始使用以下代碼關(guān)閉數(shù)據(jù)庫(kù):
fun destroyInstance() {
if (INSTANCE?.isOpen == true) {
INSTANCE?.close()
}
INSTANCE = null
}
并實(shí)現(xiàn)了如下導(dǎo)入數(shù)據(jù)庫(kù)
fun importaBkpObservable(origin: File, database: File) {
disposable.clear()
setFlagsNull()
flagSubject.onNext(false)
disposable.add(
Observable.fromCallable {
try {
repo.closeDatabase()
val myDb = SQLiteDatabase.openOrCreateDatabase(origin, null)
val ok = myDb.isDatabaseIntegrityOk
if (myDb.isOpen) myDb.close()
if(ok) {
origin.copyTo(database, true)
} else {
"CORRUPTED DATABASE"
}
} catch (t: Throwable) {
t.message
}
}
.subscribeOn(Schedulers.io())
.subscribe(
{
if(it != null) {
if(it is String) {
errorFlag = "exportDB: $it"
errorSubject.onNext("exportDB: $it")
} else {
trueFlag = true
flagSubject.onNext(true)
}
} else {
errorFlag = "exportDB: GENERIC"
errorSubject.onNext("exportDB: GENERIC")
}
},
{
errorFlag = "exportDB: ${it.message}"
errorSubject.onNext("exportDB: ${it.message}")
}
)
)
}
我曾經(jīng)通過(guò)startActivityForResult()從我的主要活動(dòng)導(dǎo)航到導(dǎo)入/導(dǎo)出活動(dòng),但現(xiàn)在已經(jīng)更改為startActivity()在此調(diào)用之后完成我的主要活動(dòng).導(dǎo)入/導(dǎo)出完成后,我使用startActivity()調(diào)用我的主活動(dòng),然后完成導(dǎo)入/導(dǎo)出活動(dòng).
這樣我的主要活動(dòng)ViewModel再次使用新的AppDatabase實(shí)例進(jìn)行實(shí)例化,并且一切正常.
我查看了Android Profiler,經(jīng)過(guò)多次導(dǎo)入和導(dǎo)出后,內(nèi)存使用量介于90 MB到130 MB之間,與之前沒(méi)有關(guān)閉數(shù)據(jù)庫(kù)時(shí)一樣,所以我想我沒(méi)有遇到某種內(nèi)存泄漏或累積Room Databases實(shí)例.
我還應(yīng)該檢查什么?
標(biāo)簽:android,android-room
來(lái)源: https://codeday.me/bug/20190622/1262676.html
總結(jié)
以上是生活随笔為你收集整理的android代码打开数据库,android – 如何正确关闭并重新打开Room数据库的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: mysql 数据类型怎么用,myMySQ
- 下一篇: oracle ora 47306,Ora