You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android中如何检测SQLite连接的开启与关闭状态变化?

检测SQLCipher(Room)连接关闭状态的方案

针对你的需求,这里提供两种可靠的方案,避免依赖不可靠的onDestroy方法:

方案1:利用SQLCipher原生连接监听(推荐)

SQLCipher的SQLiteDatabase提供了SQLiteConnectionListener接口,可以监听单个连接的打开/关闭事件。结合Room的回调,我们可以通过维护连接计数来判断数据库整体的可用状态:

步骤1:维护状态变量与监听逻辑

先定义用于跟踪连接状态的变量,以及状态变化的通知机制:

// 线程安全的连接计数器
private val connectionCount = AtomicInteger(0)
// 标记数据库是否处于可用状态
private var isDatabaseActive = false
// 存储状态变化监听器,供通知服务订阅
private val stateChangeListeners = mutableListOf<(Boolean) -> Unit>()

// 供通知服务注册状态监听
fun addStateChangeListener(listener: (Boolean) -> Unit) {
    stateChangeListeners.add(listener)
}

// 广播状态变化
private fun notifyStateChanged(isActive: Boolean) {
    stateChangeListeners.forEach { it.invoke(isActive) }
}

// 自定义SQLCipher连接监听器
private inner class DbConnectionListener : SQLiteConnectionListener {
    override fun onOpen() {
        val newCount = connectionCount.incrementAndGet()
        // 第一个连接打开时,标记数据库为可用
        if (newCount == 1 && !isDatabaseActive) {
            isDatabaseActive = true
            notifyStateChanged(true)
        }
    }

    override fun onClosed() {
        val newCount = connectionCount.decrementAndGet()
        // 最后一个连接关闭时,标记数据库为不可用
        if (newCount == 0 && isDatabaseActive) {
            isDatabaseActive = false
            notifyStateChanged(false)
        }
    }
}

步骤2:修改Room初始化逻辑,添加回调

在构建Room数据库时,通过RoomDatabase.Callback获取SQLCipher的数据库实例,并添加监听器:

fun initialize(passphrase: String): Boolean {
    this.passphrase = SQLiteDatabase.getBytes(passphrase.toCharArray())
    this.factory = SupportFactory(this.passphrase, PasswordValidationHook(), false)

    return try {
        val dbCallback = object : RoomDatabase.Callback() {
            override fun onOpen(db: SupportSQLiteDatabase) {
                super.onOpen(db)
                // 将Room的SupportSQLiteDatabase转换为SQLCipher的实例,添加连接监听器
                (db as? SQLCipherSupportSQLiteDatabase)?.database?.let { sqliteDb ->
                    sqliteDb.addConnectionListener(DbConnectionListener())
                }
            }
        }

        myDatabase = Room.databaseBuilder(
            context.applicationContext,
            MyDatabase::class.java,
            DATABASE_NAME
        )
            .openHelperFactory(factory)
            .addCallback(dbCallback)
            .build()

        myDatabase.query("SELECT 1", emptyArray())
        true
    } catch (e: Exception) {
        false
    }
}

方案优势

  • 能捕获主动关闭连接和意外断开两种场景
  • 通过连接计数准确判断数据库整体可用状态(连接池中有至少一个连接则为开启)
  • 无需依赖生命周期方法,可靠性更高

方案2:监听RoomDatabase的主动关闭(补充)

如果只需要捕获主动调用close()的场景,可以通过包装RoomDatabase来监听关闭操作:

class TrackableRoomDatabase(private val delegate: RoomDatabase) : RoomDatabase() {
    override fun close() {
        super.close()
        // 主动关闭时通知状态变化
        notifyStateChanged(false)
    }

    // 代理RoomDatabase的所有核心方法(如query、inTransaction等)
    override fun query(sql: String, args: Array<out Any>?): Cursor {
        return delegate.query(sql, args)
    }

    // 其他需要代理的方法...
}

这种方式简单但有局限性,无法处理连接意外断开的情况,仅作为方案1的补充。


内容的提问来源于stack exchange,提问作者Captain Jacky

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.18 00:45:33