Kotlin中Cursor.requery()已废弃,应使用何种替代方案?
替代Cursor.requery()的正确做法
Cursor.requery()在API 15被废弃的核心原因是它会同步阻塞UI线程,导致界面卡顿甚至ANR。官方要求的「重新请求新Cursor」,本质是每次数据变更后,重新执行查询获取新的Cursor实例,再用新Cursor更新列表,同时推荐异步执行数据库操作避免阻塞主线程。
针对你的代码,修复步骤如下:
1. 封装查询逻辑,避免重复代码
把查询数据库的操作抽成单独方法,每次需要刷新数据时调用,同时记得关闭旧Cursor防止内存泄漏:
private fun queryNewCursor(): Cursor { // 先关闭旧Cursor(如果存在) if (::rs.isInitialized && !rs.isClosed) { rs.close() } // 重新执行查询获取新Cursor return db.rawQuery("SELECT * FROM TABLE LIMIT 20", null) }
2. 用异步方式执行查询(Kotlin协程实现)
数据库操作属于耗时IO,必须放在后台线程。用Kotlin协程的launch+Dispatchers.IO可以轻松实现异步:
btnDelete.setOnClickListener { // 先执行删除操作 db.delete("TABLE", "_id=?", arrayOf(rs.getString(0))) // 后台线程查询新Cursor,主线程更新UI lifecycleScope.launch(Dispatchers.IO) { val newCursor = queryNewCursor() withContext(Dispatchers.Main) { // 用新Cursor更新Adapter,Adapter会自动关闭旧Cursor adapter.changeCursor(newCursor) // 更新全局的rs变量为新Cursor rs = newCursor } } }
3. 初始化Adapter时的调整
在onCreate里初始化Adapter时,也要确保正确关联Cursor:
override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) val helper = MyHelper(applicationContext) db = helper.readableDatabase rs = queryNewCursor() // 用封装的方法初始化Cursor // 假设你的Adapter初始化代码类似这样(根据实际布局调整参数) adapter = SimpleCursorAdapter( this, android.R.layout.simple_list_item_1, rs, arrayOf("column_name"), // 替换为你的表中要显示的列名 intArrayOf(android.R.id.text1), 0 ) // 假设你有一个ListView或RecyclerView设置Adapter listView.adapter = adapter }
关键注意点
- 永远不要在主线程执行数据库查询/写入操作,必须用异步方式(协程、AsyncTask等,推荐协程)。
- 使用
adapter.changeCursor(newCursor)替代requery(),这个方法会自动关闭旧的Cursor,避免内存泄漏。 - 页面销毁时记得关闭Cursor和数据库连接,在
onDestroy中添加:
override fun onDestroy() { super.onDestroy() if (::rs.isInitialized && !rs.isClosed) { rs.close() } db.close() }
内容的提问来源于stack exchange,提问作者galailaptrinh
相关产品推荐
相关产品推荐

