android - 在 Kotlin 中将 Callback 转换为可暂停的协程
问题描述
我目前有一个回调,它不是同步返回一个值,而是需要做一些异步工作,然后返回结果。我一直在研究如何做到这一点,但我不清楚。到目前为止,我所取得的成就是这样的,但是由于我需要在 foo 方法中添加一个 return,所以首先它返回“something”,然后返回调用 someMethod() 的结果。
我假装的可能吗?
class CustomClass() :
SomeClass.SomeInterface {
override fun foo(p0: SomeType): String {
val result = "something"
MainScope().launch {
withContext(Dispatchers.IO) {
result = someMethod()
}
}
return result
}
suspend fun someMethod(): String =
suspendCancellableCoroutine { cancelableContinuation ->
//TODO: register some listener that will end up calling
cancelableContinuation.resume("some_value", {})
}
提前致谢!
解决方案
您不能同步返回结果,因此foo
必须定义为挂起函数。
此外,没有理由将挂起函数调用包装在withContext
. 挂起函数(如果组合正确)在内部包装任何阻塞代码,因此它们可以安全地从任何调度程序调用,因此没有理由指定一个使用withContext
如果你withContext
去掉你没有等待的协程的启动,foo()
除了调用之外什么都不做,所以你可以把someMethod
代码从. 但必须定义为函数。someMethod
foo
foo
suspend
override suspend fun foo(p0: SomeType): String = suspendCancellableCoroutine { continuation ->
val request = someApi.request(p0) { result: String ->
continuation.resume(result)
}
continuation.invokeOnCancellation {
request.cancel()
}
}
通常,您不希望像这样的模型类从它们自己的 CoroutineScopes 启动协程。只需让他们公开挂起功能即可。由 Activity、Fragment 和 ViewModel 等更高级别的类来从其所需范围启动协程,以便它们可以控制协程生命周期。
推荐阅读
- python - model.fit_generator 中的 steps_per_epoch 实际上在做什么?
- c# - 在 DataTable C# 中比较和查找行值
- next.js - 在 NextJS 中设置目录的正确方法
- python-3.x - 数据帧到 csv 文件不包括数字(表中的浮点数)和清理 '\n'
- python - Django 验证返回两个错误而不是一个
- c# - C# Windows 窗体使用 SQLite 数据库,打开连接时为 NullReference
- database - 获取数据库连接错误。MariaDB 经常关闭。该怎么办?
- python - 将数字添加到列表中的重复字符串
- php - laravel 7 'laravel.password_resets' 不存在
- sql - Oracle 按问题分组 sql 查询