【问题标题】:Kotlin coroutine immediately give an exception if last operation finished with exception如果最后一个操作以异常结束,Kotlin 协程立即给出异常
【发布时间】:2018-10-14 16:04:17
【问题描述】:

当我尝试通过改造登录我的服务时。当我的服务关闭时,单击按钮 10 秒后,我收到了 SocketTimeoutException 异常。 到目前为止一切正常,但是在错误立即给出相同的错误后,我再次单击了该按钮。怎么了?

interface LoginService {

    @FormUrlEncoded
    @POST("/login")
    fun login(@Field("id") id: String, @Field("pw") pw: String): Deferred<Response<User>>

}

class LoginViewModel : ViewModel() {

    private var job: Job = Job()
    private val scope: CoroutineScope = CoroutineScope(Dispatchers.Main + job)
    private val service by lazy { RetrofitApiFactory().create(LoginService::class.java) }
    private val excHandler = CoroutineExceptionHandler { _, throwable ->
        Timber.e(throwable);
    }

    fun doLogin(id: String, pw: String) {
        scope.launch(excHandler) {
            val response = service.login(id, pw).await()
            if (response.isSuccessful) {
                response.body()
                        ?.let { user -> doOnSuccess(user) }
                        ?: doOnError(InvalidUserException())
            } else doOnError(Exception())
        }
    }

    private fun CoroutineScope.doOnError(e: Throwable) {
        excHandler.handleException(coroutineContext, e)
    }

    private fun doOnSuccess(user: User) {
        ...
    }

    override fun onCleared() {
        job.cancel()
    }

}

【问题讨论】:

  • 我发现这个设计有一个很大的问题,它有几个渠道来传达错误。首先是Response,它可能成功或失败,然后是Deferred,它可能完成或取消。在一个好的设计中,不会有Deferred,而是suspend fun,它会通过异常发出所有错误的信号。如果您得到响应,则表示成功。
  • 请参阅 here 以全面了解 suspend funDeferred 背后的理念。
  • 如果没有Deferred,我将无法使用。它给出一个错误:java.lang.IllegalArgumentException: Unable to create call adapter for retrofit2.Response
  • 是的,据我所知,Retrofit 只支持Deferred,但我认为它也应该支持suspend fun。您是否将您的函数声明为suspend fun
  • Heresuspend fun 支持将在 Kotlin 1.3 发布后立即发布。

标签: kotlin kotlinx.coroutines


【解决方案1】:

您需要更改您的CoroutineScope 以不重复使用相同的Job。它已经被视为失败,因此它甚至不会开始执行。

related issue on github

【讨论】:

  • 这个建议是致命的错误,它首先消除了主作业存在的原因。最好的建议是不要让异常在未处理的情况下逃逸。如果这不是一个选项,那么从 GitHub 问题中获取建议并使用 SupervisorJob 而不是 Job
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-08-12
  • 2018-05-26
  • 1970-01-01
  • 2018-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-04-13
相关资源
最近更新 更多