Room是否自动缓存compileStatement调用?是否需自行缓存?
Room中compileStatement的缓存问题解答
首先明确:Room不会自动缓存通过compileStatement生成的SQLiteStatement实例,你每次调用这个方法,都会重新编译SQL语句并创建新的Statement对象——也就是你代码里的stmt每次调用都会重新生成。
如果这个更新方法会被频繁调用,重复编译SQL的开销会累积,建议你自行缓存这个Statement来优化性能。
优化示例(线程安全版)
因为SQLiteStatement本身不是线程安全的,所以可以用ThreadLocal来为每个线程缓存独立的实例:
// 定义ThreadLocal缓存Statement private val updateStmtCache = ThreadLocal<SQLiteStatement>() fun updateAllowMessagesByInRangeRegularUsersAllRows(database: GeneratedDatabase, allowMessagesByInRangeRegularUsers: Boolean) { assert(database.inTransaction()) // 从缓存获取或创建Statement val stmt = updateStmtCache.get() ?: run { val newStmt = database.compileStatement("update Conversation set allowMessagesByInRangeRegularUsers = ?") updateStmtCache.set(newStmt) newStmt } val val1 = if (allowMessagesByInRangeRegularUsers) 1L else 0L stmt.bindLong(1, val1) stmt.execute() // 注意:如果不需要再复用,记得在合适的时机关闭Statement并清理ThreadLocal }
补充说明
- 如果这个方法只是偶尔调用,重新编译的开销几乎可以忽略,没必要缓存;
- 缓存时一定要注意线程安全,绝对不能多个线程共用同一个SQLiteStatement实例;
- 当数据库关闭或者不再需要这个Statement时,要记得调用
stmt.close()释放资源,避免内存泄漏。
内容的提问来源于stack exchange,提问作者J. Doe
相关产品推荐
相关产品推荐

