android 如何修复Kotlin作业取消异常?

0s7z1bwu  于 2022-12-09  发布在  Android
关注(0)|答案(7)|浏览(277)

由于Kotlin作业取消异常,我遇到了崩溃。
以下是有关崩溃的详细信息:

kotlinx.coroutines.JobCancellationException: Job was cancelled; job=SupervisorJobImpl{Cancelling}@131dbe3

我所知道的是SupervisorJobImpl用于ViewModelScope,并且在ViewModel生命周期结束时将调用方法cancel
我对这个异常感到很困惑,因为Kotlin协程会忽略这个异常,但它被抛出并导致应用程序崩溃。如果它有堆栈,我可以计算出来,但它没有,只要告诉我作业被取消了。
我花了大约3天以上的例外,但只是不知道。
我看了录像:KotlinConf 2019: Coroutines! Gotta catch 'em all! by Florina Muntenescu & Manuel Vivo,我发现如果取消了作用域,并且如果在Deferred上调用await,它将抛出异常,但是我在取消的作用域上没有发现await
所以,有人能给我看一些代码,这可能会导致同样的异常,使应用程序崩溃?谢谢。

ctehm74n

ctehm74n1#

最后,我找到了导致Exception的原因,并且问题地址如下:
kotlin.coroutines.channels.awaitClose: JobCancellationException
实际上,awaitClose不会抛出JobCancellationException,因为awaitClose是一个可取消的挂起函数。如果作业被取消,offer方法将抛出JobCancellationException,因为offer不是一个可取消的挂起函数。
顺便说一下,callbackFlow是一个实验性的API,所以它可能会引起一些bug,所以我们在使用它的时候,需要小心。因为它不会总是在作业被取消时忽略JobCancellationException,我认为它对开发者不友好。
现在,我发现了2种会导致JobCancellationException的情况,因此我们需要try catch异常。

  1. async await,当我们调用await方法时,我们需要try catch。你可以在Video中找到一个例子。
  2. callbackFlow offer,当我们调用offer方法时,我们需要try catch。你可以在上面的问题中找到一个例子。
lnlaulya

lnlaulya2#

我知道我迟到了,但你可以在提供对象之前检查作业状态。

if(isActive) offer(Resource.success(response))

isActive是协程作用域

1mrurvl1

1mrurvl13#

我刚刚看到了同样的问题。这个问题是由活动在作业设法完成之前手动完成引起的。

093gszye

093gszye4#

1.我关闭了一个ViewModel和一个对话框,然后启动了一个Job。它导致了这个异常和HTTP请求取消:HTTP FAILED: java.io.IOException: Canceled

close()
modelScope.launch {
    val response = withContext(Dispatchers.IO) {
        ...
    }
    response?.let { ... }
}

我只是简单地将close()移到了末尾。
1.有一种情况,当一切都运行良好,但是每100次点击中就有一次协程自行取消(同样的“HTTP FAILED:java.io.IOException:取消”)。没有任何帮助,直到我把lifecycleScope.launch改为lifecycleScope.launchWhenResumed

8ljdwjyq

8ljdwjyq5#

class MyApp: Application() {

    override fun onCreate() {
        super.onCreate()
        System.setProperty(DEBUG_PROPERTY_NAME, DEBUG_PROPERTY_VALUE_ON)
       
    }

这样你就能找出问题的主要原因并加以处理

vvppvyoh

vvppvyoh6#

我有和你一样的bug。所以我试着写简单的流扩展如下:

fun <P> Flow<DataResult<P>>.safeStart(start: suspend FlowCollector<DataResult<P>>.() -> Unit)
        : Flow<DataResult<P>> =  onStart {
        if (!currentCoroutineContext().isActive) return@onStart
        start()
    }

fun <P> Flow<DataResult<P>>.safeCatch(onCatch: suspend FlowCollector<DataResult<P>>.(cause: Throwable) -> Unit)
        : Flow<DataResult<P>> = catch {
        if (!currentCoroutineContext().isActive) return@catch
        onCatch(it)
}

suspend inline fun <P> Flow<DataResult<P>>.safeCollect(crossinline onCollect: suspend (value: DataResult<P>) -> Unit)
        : Unit = collect {
    if (!currentCoroutineContext().isActive) return@collect
    onCollect(it)
}
zzzyeukh

zzzyeukh7#

当我使用callbackFlowoffer的协程版本1.3.5时,也有同样的崩溃。现在我使用trySend而不是offer,它被修复了。
注意:当您将协程版本更新为以下版本时,trySend方法可用(offer已过时):

org.jetbrains.kotlinx:kotlinx-coroutines-core:1.4.0

相关问题