我正在将一些旧的 RxJava 代码移植到协程中。使用 RxJava,我可以在我的活动中执行此操作:
someBgOperation()
.as(AutoDispose.autoDisposable(AndroidLifecycleScopeProvider.from(MyActivity.this)))
.subscribe(
MyActivity.this::onSuccess,
MyActivity.this::onError
);
如果活动正在关闭,自动处置库将取消 Observable。在这种情况下,RxJava 不会调用错误处理程序,因此可以在错误处理程序中安全地执行与 UI 相关的操作,例如显示对话框。
现在,在 Kotlin 中,我们可以从以下位置启动等效代码lifecycleScope
在活动中,或在viewModelScope
如果使用 ViewModel:
viewModelScope.launch {
try {
someBgOperation()
} catch (e: Exception){
//show dialog
}
}
当活动关闭时,两个作用域都会自动取消,就像 Autodispose 所做的那样。但是 catch 块不仅会在抛出正常错误时执行someBgOperation
本身,但也与CancellationException
协程库在幕后使用它来处理取消。如果我尝试在活动关闭时显示一个对话框,我可能会遇到新的异常。所以我被迫做这样的事情:
viewModelScope.launch {
try {
someBgOperation()
} catch (ce: CancellationException){
//do nothing, activity is closing
} catch (e: Exception){
//show dialog
}
}
这感觉比 Rx 版本更详细,并且有一个空的 catch 子句,这会在 lint 输出中显示警告。在其他情况下,如果我在 try-catch 之后执行更多操作,我将被迫从CancellationException
catch 以保持 UI 安全(并且这些返回值被标记为返回值)。我发现自己一次又一次地重复这个丑陋的模板。
有没有更好的方法来忽略 CancellationException?