我想要的是这样的功能:
suspendCoroutineWithTimeout(timeout: Long, unit: TimeUnit, crossinline block: (Continuation<T>) -> Unit)
这与现有的suspendCoroutine
函数基本相同,但是如果回调或块中提供的任何内容在指定的超时内被调用,则corutine会继续,但是会出现TimeoutException或者像这一点。
答案 0 :(得分:7)
您可以直接合并withTimeout
和suspendCancellableCoroutine
以获得所需的效果:
suspend inline fun <T> suspendCoroutineWithTimeout(
timeout: Long, unit: TimeUnit,
crossinline block: (Continuation<T>) -> Unit
) = withTimeout(timeout, unit) {
suspendCancellableCoroutine(block = block)
}
答案 1 :(得分:1)
如果你正在使用suspendCoroutine
,那意味着你完全可以控制你所做的延续。例如,您可以将其传递给基于回调的异步API,此外,还可以将其传递给将执行的计划任务,但例外情况为:
suspend fun mySuspendFun(timeout: Long): String {
val didResume = AtomicBoolean()
fun markResumed() = !didResume.getAndSet(true)
return suspendCoroutine { cont ->
launch(CommonPool) {
delay(timeout)
if (markResumed()) {
cont.resumeWithException(TimeoutException())
}
}
// call Async API, and in the callback, use
// if (markResumed()) {
// cont.resume(result)
// }
}
}
但是,Kotlin的标准库支持您的第一类用例,如Roman Elizarov's answer中所述。我建议你在项目中使用这种方法。
答案 2 :(得分:1)
@Roman Elizarov的完美回答。只是在上面加上我的2美分,因为我需要从该通话中返回。返回它将是...
suspend inline fun <T> suspendCoroutineWithTimeout(timeout: Long, crossinline block: (Continuation<T>) -> Unit ) : T? {
var finalValue : T? = null
withTimeoutOrNull(timeout) {
finalValue = suspendCancellableCoroutine(block = block)
}
return finalValue
}
答案 3 :(得分:0)
suspend inline fun <T> suspendCoroutineWithTimeout(
timeout: Long,
crossinline block: (CancellableContinuation<T>) -> Unit
): T? {
var finalValue: T? = null
withTimeoutOrNull(timeout) {
finalValue = suspendCancellableCoroutine(block = block)
}
return finalValue
}
suspend inline fun <T> suspendCoroutineObserverWithTimeout(
timeout: Long,
data: LiveData<T>,
crossinline block: (T) -> Boolean
): T? {
return suspendCoroutineWithTimeout<T>(timeout) { suspend ->
var observers : Observer<T>? = null
val oldData = data.value
observers = Observer<T> { t ->
if (oldData == t) {
KLog.e("参数一样,直接return")
return@Observer
}
KLog.e("参数不一样,刷新一波")
if (block(t) && !suspend.isCancelled) {
suspend.resume(t)
observers?.let { data.removeObserver(it) }
}
}
data.observeForever(observers)
suspend.invokeOnCancellation {
KLog.e("删除observiers")
observers.let { data.removeObserver(it) }
}
}
}
之前@Roman Elizarov和@febaisi的回答已经回答的很好了,我在此基础上加了类型判断和livedata,满足条件才会返回。对不起,我的英语不是很好。 ——