首页 > 解决方案 > 不阻塞将查询结果返回到主线程

问题描述

我在使用 Kotlin 协程时遇到问题,我正在尝试查询数据库并将结果返回到主线程,但如果不“冻结”我的主线程,我无法弄清楚如何做到这一点。在这种情况下,runBlocking 将是罪魁祸首,但我不确定用什么来代替它。非常感谢任何和所有帮助!

fun getResults() : List<String> {
    val results = ArrayList<String>()

    runBlocking {
        viewModelScope.launch(Dispatchers.IO) {
            openConnection()

            try {
                statement = connection!!.createStatement()
                resultSet = statement!!.executeQuery("blah blah blah")
                while (resultSet != null && resultSet!!.next()) {
                    results.add(resultSet!!.getString(1))
                }
            } catch (e: Exception) {
                Log.d("getList Catch", e.toString())
            }

            closeConnection()
        }.join()
    }

    return results
}

标签: androidasynchronouskotlinreturncoroutine

解决方案


runBlocking当与可挂起的协程或回调一起适当地确定阻塞任务的范围时,不需要。

如上所述,您有几个选择:

可挂起的协程

suspend fun getResults() : List<String> = suspendCancellableCoroutine { cont ->

    openConnection()

    val results = ArrayList<String>()

    try {
        statement = connection!!.createStatement()
        resultSet = statement!!.executeQuery("blah blah blah")
        while (resultSet != null && resultSet!!.next()) {
            results.add(resultSet!!.getString(1))
        }
        closeConnection()
        cont.resumeWith(Result.success(results))
    } catch (e: Exception) {
        Log.d("getList Catch", e.toString())
        closeConnection()
        cont.resumeWith(Result.failure(e))
    }
}

匿名回调

fun getResults(cb: (List<String>) -> Unit) {
    viewModelScope.launch(Dispatchers.IO) {
        openConnection()

        val results = ArrayList<String>()

        try {
            statement = connection!!.createStatement()
            resultSet = statement!!.executeQuery("blah blah blah")
            while (resultSet != null && resultSet!!.next()) {
                results.add(resultSet!!.getString(1))
            }
        } catch (e: Exception) {
            Log.d("getList Catch", e.toString())
        }
        cb.invoke(results)
        closeConnection()
    }
}

我个人的偏好是第二个选项,因为它消除了该方法的使用者必须意识到并实现可暂停的需要。

launch(Dispatchers.IO) {
   val results = getResults()
   // handle results
}

对比

getResults {
   // handle results
}

推荐阅读