Kotlin协程处理错误和实现 [英] Kotlin coroutines handle error and implementation
问题描述
首次使用协程.需要帮助.
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>?
我的问题是:
- 我的方法在架构上是否正确?
- 如何在我的代码中传递http错误代码或没有互联网连接
- 还有什么更好的方法可以解决我的问题?
推荐答案
在本地范围内启动协程是一个好习惯,可以在生命周期感知类中实现该协程,例如 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:
-
在单独的文件中创建
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
函数可挂起并在RepositoryInterface
和Repository
中返回Result
:
Make onUserLogin
function suspendable and returning Result
in RepositoryInterface
and Repository
:
suspend fun onUserLogin(loginRequest: LoginRequest): Result<LoginResponse> {
return apiInterface.makeLoginCall(loginRequest)
}
根据以下代码更改APIInterface
和APIInterfaceImpl
中的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屋!