Reputation: 1257
What I want is a function like this:
suspendCoroutineWithTimeout(timeout: Long, unit: TimeUnit, crossinline block: (Continuation<T>) -> Unit)
That does basically the same thing as the existing suspendCoroutine
function but if the callback or whatever was provided in the block dosen't get called within the specified timeout the corutine continues but with a TimeoutException or something like that.
Upvotes: 23
Views: 11116
Reputation: 11
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) }
}
}
}
The previous @Roman Elizarov and @febaisi answers have been answered very well, I added a type judgment and livedata on this basis, and I will return only when the conditions are met. Sorry, my English is not very good. –
Upvotes: 0
Reputation: 684
Perfect answer from @Roman Elizarov.. Just adding my 2 cents on it because I needed a return from that call.. So adding T? return it would be ...
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
}
Upvotes: 16
Reputation: 28648
You can combine withTimeout
and suspendCancellableCoroutine
in a straightforward way for the desired effect:
suspend inline fun <T> suspendCoroutineWithTimeout(
timeout: Long, unit: TimeUnit,
crossinline block: (Continuation<T>) -> Unit
) = withTimeout(timeout, unit) {
suspendCancellableCoroutine(block = block)
}
Upvotes: 68