将查询结果返回主线程而不阻塞

时间:2019-08-18 22:02:17

标签: android asynchronous kotlin return coroutine

我在使用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
}

1 个答案:

答案 0 :(得分:1)

  

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
}

vs。

getResults {
   // handle results
}