如何在后台调用一个函数,既不阻塞线程,又在Kotlin中等待返回



我有一个函数可以调用内部FFI代码,该代码可能会阻塞UI:

fun query(q: Request): Response {
val cmd = Json.encodeToString(q)

// This could take long...
result = Server.server.query(cmd):
return try {
Json.decodeFromString<Response>(result)
} catch (e: Exception) {
Response.Fail(UIData.JsonError(kind = "JSON Decode", message = e.toString()))
}
}

我不想为了这个而把我所有的代码都变成异步。我想用一种UI不会冻结但仍在等待结果的方式来调用它。

我尝试了GlobalScope.launch,但它没有返回结果,并且不能在这里放置通道,因为获取结果需要挂起函数。

函数签名fun query(q: Request): Response定义了一个函数,该函数阻塞当前线程,直到Response可用并返回。没有办法绕过它。

如果您不想阻塞当前线程,则必须更改签名,这样函数才能变得异步。一种方法是标记函数suspend,这很好,因为您不需要对代码的设计进行太多更改,并且可以按顺序进行推理。另一种方法是提供回调以便稍后使用结果。

如果您决定将函数标记为suspend,那么您仍然没有完成。Server.server.query可能也会阻塞,所以您要么需要将其封装在withContext(Dispatchers.IO)中,要么最好找到一个异步替代方案,这样您就可以真正挂起它。

如果可以更改函数的签名以返回Deferred<Response>,则可以将阻塞查询封装在GlobalScope.async(Dispatchers.IO) {}

最新更新