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

将RecyclerView数据获取改为协程的相关问题及Cursor处理疑问

问题解答

一、为什么协程中调用LiveData.setValue()会抛出异常?

你在viewModelScope.launch(Dispatchers.IO)里调用setValue()报错,核心原因是LiveData的setValue()方法强制要求在主线程执行,而你显式指定了Dispatchers.IO,协程运行在IO后台线程,违反了这个规则,所以抛出IllegalStateException。

  • viewModelScope的默认调度器是Dispatchers.Main,如果不指定Dispatchers.IO,协程会在主线程运行,此时调用setValue()是合法的。
  • postValue()的作用是把LiveData的更新任务提交到主线程的消息队列,由主线程执行实际的setValue()操作,因此不会触发线程检查。

二、Cursor的关闭警告该如何处理?

绝对不能在调用postValue()后直接调用cursor.close()——因为此时RecyclerView还需要使用这个Cursor加载数据,提前关闭会导致后续操作抛出CursorWindowAllocationException之类的错误。

正确的处理方式:

  • 在LiveData的观察者中管理Cursor生命周期:当观察者收到新Cursor时,关闭之前的旧Cursor。示例如下:
    private var oldCursor: Cursor? = null
    
    dbCursor.observe(viewLifecycleOwner) { newCursor ->
        oldCursor?.close()
        oldCursor = newCursor
        adapter.swapCursor(newCursor)
    }
    
  • 避免使用!!强制非空:contentResolver.query()可能返回null(比如权限不足、URI错误),直接用!!会引发空指针异常,应该保留null并在后续处理:
    val cursor = getApplication<Application>().contentResolver.query(...)
    dbCursor.postValue(cursor)
    
  • 页面生命周期结束时清理:在Fragment/Activity的onDestroy()中,获取LiveData当前持有的Cursor并关闭:
    override fun onDestroy() {
        super.onDestroy()
        dbCursor.value?.close()
        oldCursor?.close()
    }
    

完整代码(修正后)

private fun loadTasks() {
    val func = "loadTasks"
    Log.d(TAG, func)
    val projection = arrayOf(
        TasksContract.Columns.ID,
        TasksContract.Columns.TASK_NAME,
        TasksContract.Columns.TASK_DESCRIPTION,
        TasksContract.Columns.TASK_SORT_ORDER
    )
    val sortOrder = "${TasksContract.Columns.TASK_SORT_ORDER}, ${TasksContract.Columns.TASK_NAME}"
    viewModelScope.launch(Dispatchers.IO) {
        val cursor = getApplication<Application>().contentResolver.query(
            TasksContract.CONTENT_URI, projection, null, null, sortOrder
        )
        dbCursor.postValue(cursor) // 移除!!,允许null
    }
    Log.d(TAG, "$func done")
}

内容的提问来源于stack exchange,提问作者Ben Edwards

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 09:20:29