我使用kotlin开发了一个android应用程序。我使用swagger获取所有Web服务。
我想调用Web服务并使用try / catch处理错误(如果存在)。
经过一段时间的有关如何使用此WS的研究,我发现我应该将协程与Dispatchers一起使用,并使用GlobalScope如下:

         GlobalScope.launch(Dispatchers.Default) {
  val productsType = mobileApi.apiMobileProductTypeGetAllPost(params, 0, 50, "", "")
withContext(Dispatchers.Main) {
    viewProductType.loadAllTypeProduct(productsType)}

这是loadAllTypeProduct的代码:
override fun loadAllTypeProduct(data: Array<ProductTypeData>) {
        recyclerViewProductTypeList.apply {
            recyclerViewProductTypeList.layoutManager = LinearLayoutManager(context, RecyclerView.HORIZONTAL, false)
            recyclerViewProductTypeList.adapter = ProductTypeItemAdapter(data, this@HomeFragment, context)
        }
    }

但是,我发现我应该使用协程范围而不是全局范围,并且强烈不建议使用全局范围。
因此,我将代码从上面的代码更改为以下代码:
   val scope = CoroutineScope(Dispatchers.Main)
        basicViewInterface.showProgressBar()
        val task = scope.launch {
            try {
               withContext(Dispatchers.IO) {
                   val productsType=  mobileApi.apiMobileProductTypeGetAllPost(params, 0, 50, "", "")
                   viewProductType.loadAllTypeProduct(productsType)
                }
                basicViewInterface.hideProgressBar()
            } catch (e: Throwable) {
                e.printStackTrace()
            }
        }
        if (task.isCancelled){
            basicViewInterface.displayError("error")
        }

我想调用WS并使用try / catch处理异常,并在Toast中显示错误,我该怎么做。

最佳答案

协程范围的要点是,它在您检测到用户已离开当前 Activity 的位置可用,因此您可以在一个中心位置将其取消并取消所有子协程。您所做的更改(仅创建一个局部的,一次性的作用域)与使用GlobalScope一样糟糕。如果您的代码在Activity或Fragment中,则使该类实现CoroutineScope by MainScope,您可以在CoroutineScopedocumentation中看到更详细的示例。

至于处理异常,代码在发布时看起来应该很漂亮,只需要注意切换上下文即可。协程范围应将Main指定为调度程序,并且仅应针对阻塞的网络调用切换到IO,如下所示:

basicViewInterface.showProgressBar()
scope.launch {
    try {
        val productsType = withContext(Dispatchers.IO) {
            mobileApi.apiMobileProductTypeGetAllPost(params, 0, 50, "", "")
        }
        viewProductType.loadAllTypeProduct(productsType)
        basicViewInterface.hideProgressBar()
    } catch (e: Throwable) {
        basicViewInterface.displayError("error")
    }
}

如果将withContext推送到apiMobileProductTypeGetAllPost的主体中,那会更好,更干净,因为这是本地化的问题。从外部看,它应该是另一个可以调用的可挂起函数,而不必担心诸如给定实现是否在非阻塞时阻塞之类的底层细节。

我注意到其他人提到了协程异常处理程序,但我不建议您使用它。它仅在协程层次结构的顶层起作用,其目的是仅捕获由于编程错误而在业务代码中未适当处理的那些异常。它等效于Java中的Thread.uncaughtExceptionHandler

10-07 19:06
查看更多