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
相关产品推荐
相关产品推荐

