我想要的是这样的功能:
suspendCoroutineWithTimeout(timeout: Long, unit: TimeUnit, crossinline block: (Continuation<T>) -> Unit)
这与现有函数的作用基本相同,suspendCoroutine
但如果在指定的超时时间内未调用回调或块中提供的任何内容,则协程将继续,但会出现 TimeoutException 或类似的情况。
我想要的是这样的功能:
suspendCoroutineWithTimeout(timeout: Long, unit: TimeUnit, crossinline block: (Continuation<T>) -> Unit)
这与现有函数的作用基本相同,suspendCoroutine
但如果在指定的超时时间内未调用回调或块中提供的任何内容,则协程将继续,但会出现 TimeoutException 或类似的情况。
您可以以简单的方式组合withTimeout
并suspendCancellableCoroutine
获得所需的效果:
suspend inline fun <T> suspendCoroutineWithTimeout(
timeout: Long, unit: TimeUnit,
crossinline block: (Continuation<T>) -> Unit
) = withTimeout(timeout, unit) {
suspendCancellableCoroutine(block = block)
}
@Roman Elizarov 的完美回答.. 只需添加我的 2 美分,因为我需要从那个电话中获得回报.. 所以添加 T?返回它会是......
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
}
如果您正在使用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 的回答中所述。我建议你在你的项目中使用这种方法。
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,满足条件才会返回。对不起,我的英语不是很好。——</p>