首页 > 解决方案 > Kotlin 协程 - 优雅地处理来自挂起函数的错误

问题描述

尝试使用从异步方法调用的挂起函数来优雅地处理错误,如何捕获挂起方法引发的错误。

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
}

调用程序,使用 IO 线程启动

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
}

当前运行时崩溃,想要优雅地处理错误。


尝试 2

尝试将 try catch 放在异步块中,但它不喜欢它。

var userAsync: Deferred<UserVO?>? = null
arguments?.getLong("id")?.let {
    userAsync = async {
        try {
            delegate?.findById(it)
        } catch (e: Exception) {
            print(e)
        }
    }
}

标签: androidkotlinerror-handlingtry-catchkotlin-coroutines

解决方案


我会使用 aCoroutineExceptionHandler让你的协程优雅地失败:

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)
    }
}
  1. 在内部启动您的工作MainScope(并更新 ui),将 exceptionHandler 传递给启动协程构建器以捕获异常:
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())
        }
}

推荐阅读