日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 运维知识 > 数据库 >内容正文

数据库

android代码打开数据库,android – 如何正确关闭并重新打开Room数据库

發(fā)布時(shí)間:2025/3/15 数据库 40 豆豆
生活随笔 收集整理的這篇文章主要介紹了 android代码打开数据库,android – 如何正确关闭并重新打开Room数据库 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

您好我有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)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。