Kotlin协程-从暂停函数优雅地处理错误 [英] Kotlin coroutines - gracefully handling errors from suspend functions
本文介绍了Kotlin协程-从暂停函数优雅地处理错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!
问题描述
尝试使用从异步方法调用的暂停函数实现对错误的优雅处理,如何捕获由暂停方法引发的错误。
Trying to implement graceful handling of the errors with suspend functions that are called from async methods, How to catch the error thrown by a suspend method.
suspend fun findById(id: Long): User? {
throw Exception("my exception") // intentionally throwing to simulate error situation.
return userModel.findById(id) // IO, may throw an error
}
Caller件,使用IO线程启动
Caller piece, launching with IO thread
GlobalScope.launch(Dispatchers.IO) {
try {
var userAsync: Deferred<User?>? = null
arguments?.getLong("id")?.let {
userAsync = async { viewModel?.findById(it) } // async for efficiency as i've other async methods too.
}
val data = userAsync?.await()
withContext(Dispatchers.Main) {
user = data // data binding, populating UI fields of user
}
} catch (exception: Exception) {
withContext(Dispatchers.Main) { fault(exception) }
}
}
故障方法
private fun fault(exception: Exception) {
Log.d("User", "fault: ${exception.localizedMessage}") // expecting output
}
当前运行时崩溃,想要实现错误的优雅处理。
Currently runtime is crashing, want to implement graceful handling of errors.
尝试2
尝试将尝试捕获放入异步块中,但它不喜欢它。
Tried placing try catch within the async block but it didn't like it.
var userAsync: Deferred<UserVO?>? = null
arguments?.getLong("id")?.let {
userAsync = async {
try {
delegate?.findById(it)
} catch (e: Exception) {
print(e)
}
}
}
推荐答案
我将使用 CoroutineExceptionHandler
使协程正常失败:
I would use a CoroutineExceptionHandler
to make your coroutines fail gracefully:
1)定义处理程序:
val exceptionHandler = CoroutineExceptionHandler { context, error ->
// Do what you want with the error
Log.d(TAG, error)
}
2)重构您的findById函数,使其在IO上下文中执行,并使您的ui代码成为主要安全对象:
suspend fun findById(id : Int) : User? = withContext(Dispatchers.IO){
when(id){
0 -> throw Exception("not valid")
else -> return@withContext User(id)
}
}
- 在
MainScope
中启动您的工作(并因此更新ui),并传递exceptionHandler以启动协程生成器以捕获异常:
- Launch your job within
MainScope
(and so update the ui), passing exceptionHandler to launch coroutine builder in order to catch the exception:
val exceptionHandler = CoroutineExceptionHandler { _, error ->
// Do what you want with the error
Log.d(TAG, error)
}
MainScope().launch(exceptionHandler) {
val user = delegate?.findById(userId)
user?.let {
Timber.v(it.toString())
}
}
这篇关于Kotlin协程-从暂停函数优雅地处理错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!
查看全文