我正在尝试在Android上的Kotlin协程中处理异常。。
我的用例是我想在后台执行一系列任务(以异步方式),并在单个活动中更新多个UI组件。
我设计了一个BaseActivity
结构来实现CoroutineScope
,因此我可以将调用的Couroutine与活动的生命周期结合在一起。
此外,我还有一个Repository
类,用于处理网络呼叫。
我已经实现了同时运行多个任务。我知道如果我使用单个Job
对象取消活动onDestroy()
上的所有协程并在活动中执行(launch
个多个协程,那么任何单个协程中的异常都将取消{{ 1}}从其Job
。并且由于CoroutineContext
附加到活动的生命周期,它也会取消所有其他协程。
我尝试使用 Job
。它捕获异常,但也取消了CoroutineExceptionHandler
。结果取消了所有其他协程。
我想要什么?
Job
对象附加活动生命周期在下面添加代码
Job
此的日志结果是
class BaseActivity : AppCompatActivity(), CoroutineScope {
val job = Job()
override val coroutineContext: CoroutineContext
get() = Dispatchers.Main + job
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
launch(coroutineContext) {
Log.i("GURU", "launch1 -> start")
val result1Deferred = async { Repository().getData(1) }
val result2Deferred = async { Repository().getData(2) }
Log.i("GURU", "awaited result1 = " + result1Deferred.await() + result2Deferred.await())
}
//If Exception is Thrown, Launch1 should still continue to complete
advancedLaunch(coroutineContext) {
Log.i("GURU", "launch2 -> start")
val result1Deferred = async { Repository().getData(3) }
val result2Deferred = async { Repository().getData(4) }
delay(200)
throw Exception("Exception from launch 2")
Log.i("GURU", "awaited result2 = " + result1Deferred.await() + result2Deferred.await())
}
}
fun CoroutineScope.advancedLaunch(context: CoroutineContext = EmptyCoroutineContext,
exceptionBlock: (Throwable) -> Unit = {Log.i("GURU", it.message)},
launchBlock: suspend CoroutineScope.() -> Unit) {
val exceptionHandler = CoroutineExceptionHandler { _, throwable -> exceptionBlock(throwable)}
launch(context + exceptionHandler) { launchBlock() }
}
override fun onDestroy() {
super.onDestroy()
job.cancel()
Log.i("GURU", "job -> cancelled")
}
}
答案 0 :(得分:3)
您可能希望将Job
替换为SupervisorJob
。
它可以防止异常传播到“向上”(一个失败的孩子不会导致整个工作失败),但仍然允许您将取消“向下”(向正在运行的孩子)推送。