diff --git a/app/src/main/java/io/legado/app/base/adapter/RecyclerAdapter.kt b/app/src/main/java/io/legado/app/base/adapter/RecyclerAdapter.kt index 1aca74938..9c54a7de2 100644 --- a/app/src/main/java/io/legado/app/base/adapter/RecyclerAdapter.kt +++ b/app/src/main/java/io/legado/app/base/adapter/RecyclerAdapter.kt @@ -11,8 +11,8 @@ import androidx.recyclerview.widget.RecyclerView import androidx.viewbinding.ViewBinding import io.legado.app.help.coroutine.Coroutine import io.legado.app.utils.buildMainHandler +import io.legado.app.utils.withTimeoutOrNullAsync import kotlinx.coroutines.ensureActive -import kotlinx.coroutines.withTimeoutOrNull import splitties.views.onLongClick import java.util.Collections @@ -152,7 +152,7 @@ abstract class RecyclerAdapter(protected val context: Co } diffJob?.cancel() diffJob = Coroutine.async { - val diffResult = if (skipDiff) withTimeoutOrNull(500L) { + val diffResult = if (skipDiff) withTimeoutOrNullAsync(500L) { DiffUtil.calculateDiff(callback) } else { DiffUtil.calculateDiff(callback) diff --git a/app/src/main/java/io/legado/app/utils/CoroutineExtensions.kt b/app/src/main/java/io/legado/app/utils/CoroutineExtensions.kt new file mode 100644 index 000000000..abe990bce --- /dev/null +++ b/app/src/main/java/io/legado/app/utils/CoroutineExtensions.kt @@ -0,0 +1,37 @@ +package io.legado.app.utils + +import io.legado.app.help.coroutine.Coroutine +import kotlinx.coroutines.CancellationException +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.delay +import kotlinx.coroutines.launch +import kotlinx.coroutines.suspendCancellableCoroutine +import kotlin.coroutines.resume +import kotlin.coroutines.resumeWithException + +class TimeoutCancellationException(msg: String) : CancellationException(msg) + +suspend fun withTimeoutAsync(delayMillis: Long, block: suspend CoroutineScope.() -> T): T { + return suspendCancellableCoroutine { cout -> + Coroutine.async(context = cout.context) { + launch { + delay(delayMillis) + if (!cout.isCompleted) { + cout.resumeWithException(TimeoutCancellationException("Timed out waiting for $delayMillis ms")) + } + } + val result = block() + if (!cout.isCompleted) { + cout.resume(result) + } + } + } +} + +suspend fun withTimeoutOrNullAsync(delayMillis: Long, block: suspend CoroutineScope.() -> T): T? { + return try { + withTimeoutAsync(delayMillis, block) + } catch (e: TimeoutCancellationException) { + null + } +}