Kotlin协程处理错误和实现 [英] Kotlin coroutines handle error and implementation

查看:484
本文介绍了Kotlin协程处理错误和实现的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

首次使用协程.需要帮助.

Using coroutines for the first time. Need help.

这是我的流程:

演示者想要登录,因此调用存储库接口.存储库实现RepositoryInterface. 因此,存储库调用APIInterface. APIInterface由APIInterfaceImpl实现. APIInterfaceImpl最终调用MyRetrofitInterface.

Presenter wants to login so calls Repository Interface. Repository implements RepositoryInterface. So Repository calls APIInterface. APIInterface is implemented by APIInterfaceImpl. The APIInterfaceImpl finally calls the MyRetrofitInterface.

以下是流程图:

演示者->存储库-> APIInterfaceImpl-> MyRetrofitInterface

Presenter -> Repository -> APIInterfaceImpl -> MyRetrofitInterface

获得登录响应后:

APIInterfaceImpl->存储库->将数据存储在缓存中->将HTTP状态代码提供给Presenter

APIInterfaceImpl -> Repository -> Stores the data in cache -> Gives http status code to Presenter

这是我的代码:

RepositoryInterface.kt

RepositoryInterface.kt

fun onUserLogin(loginRequest: LoginRequest): LoginResponse

Repository.kt

Repository.kt

class Repository : RepositoryInterface {
   private var apiInterface: APIInterface? = null

   override fun onUserLogin(loginRequest: LoginRequest): LoginResponse {
         return apiInterface?.makeLoginCall(loginRequest)
   }
}

APIInterface.kt

APIInterface.kt

suspend fun makeLoginCall(loginRequest): LoginResponse?

APIInterfaceImpl.kt

APIInterfaceImpl.kt

override suspend fun makeLoginCall(loginRequest: LoginRequest): LoginResponse? {
        if (isInternetPresent(context)) {
            try {
                val response = MyRetrofitInterface?.loginRequest(loginRequest)?.await()
                return response
            } catch (e: Exception) {
                //How do i return a status code here
            }
        } else {
        //How do i return no internet here
            return Exception(Constants.NO_INTERNET)
        }
}

MyRetrofitInterface.kt

MyRetrofitInterface.kt

@POST("login/....")
fun loginRequest(@Body loginRequest: LoginRequest): Deferred<LoginResponse>?

我的问题是:

  1. 我的方法在架构上是否正确?
  2. 如何在我的代码中传递http错误代码或没有互联网连接
  3. 还有什么更好的方法可以解决我的问题?

推荐答案

在本地范围内启动协程是一个好习惯,可以在生命周期感知类中实现该协程,例如 Presenter ViewModel .您可以使用下一种方法来传递数据:

It is a good practice to launch a coroutine in a local scope which can be implemented in a lifecycle aware classes, for example Presenter or ViewModel. You can use next approach to pass data:

  1. 在单独的文件中创建sealed Result类及其继承者:

sealed class Result<out T : Any>
class Success<out T : Any>(val data: T) : Result<T>()
class Error(val exception: Throwable, val message: String = exception.localizedMessage) : Result<Nothing>()

  • 使onUserLogin函数可挂起并在RepositoryInterfaceRepository中返回Result:

  • Make onUserLogin function suspendable and returning Result in RepositoryInterface and Repository:

    suspend fun onUserLogin(loginRequest: LoginRequest): Result<LoginResponse> {
        return apiInterface.makeLoginCall(loginRequest)
    }
    

  • 根据以下代码更改APIInterfaceAPIInterfaceImpl中的makeLoginCall功能:

  • Change makeLoginCall function in APIInterface and APIInterfaceImpl according to the following code:

    suspend fun makeLoginCall(loginRequest: LoginRequest): Result<LoginResponse> {
        if (isInternetPresent()) {
            try {
                val response = MyRetrofitInterface?.loginRequest(loginRequest)?.await()
                return Success(response)
            } catch (e: Exception) {
                return Error(e)
            }
        } else {
            return Error(Exception(Constants.NO_INTERNET))
        }
    }
    

  • 为您的Presenter使用下一个代码:

  • Use next code for your Presenter:

    class Presenter(private val repo: RepositoryInterface,
                    private val uiContext: CoroutineContext = Dispatchers.Main
    ) : CoroutineScope { // creating local scope
    
        private var job: Job = Job()
    
        // To use Dispatchers.Main (CoroutineDispatcher - runs and schedules coroutines) in Android add
        // implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.0.1'
        override val coroutineContext: CoroutineContext
            get() = uiContext + job
    
        fun detachView() {
            // cancel the job when view is detached
            job.cancel()
        }
    
        fun login() = launch { // launching a coroutine
            val request = LoginRequest()
            val result = repo.onUserLogin(request) // onUserLogin() function isn't blocking the Main Thread
    
            //use result, make UI updates
            when (result) {
                is Success<LoginResponse> -> { /* update UI when login success */ } 
                is Error -> { /* update UI when login error */ }
            }
        }
    }
    

  • 编辑

    我们可以使用Result类上的扩展功能来替换when表达式:

    We can use extension functions on Result class to replace when expression:

    inline fun <T : Any> Result<T>.onSuccess(action: (T) -> Unit): Result<T> {
        if (this is Success) action(data)
        return this
    }
    inline fun <T : Any> Result<T>.onError(action: (Error) -> Unit): Result<T> {
        if (this is Error) action(this)
        return this
    }
    
    class Presenter(...) : CoroutineScope {
    
        // ...
    
        fun login() = launch {
            val request = LoginRequest()
            val result = repo.onUserLogin(request) 
    
            result
                .onSuccess {/* update UI when login success */ }
                .onError { /* update UI when login error */ }
        }
    }
    

    这篇关于Kotlin协程处理错误和实现的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆