第一次使用协程。需要帮助。
这是我的流程:
Presenter 想要登录所以调用 Repository Interface。 Repository 实现 RepositoryInterface。 所以 Repository 调用 APIInterface。 APIInterface由APIInterfaceImpl实现。 APIInterfaceImpl 最后调用MyRetrofitInterface。
这是流程图:
Presenter -> Repository -> APIInterfaceImpl -> MyRetrofitInterface
一旦我收到登录响应:
APIInterfaceImpl -> Repository -> 将数据存储在缓存中 -> 将 http 状态代码提供给 Presenter
这是我的代码:
存储库接口(interface).kt
fun onUserLogin(loginRequest: LoginRequest): LoginResponse
存储库.kt
class Repository : RepositoryInterface {
private var apiInterface: APIInterface? = null
override fun onUserLogin(loginRequest: LoginRequest): LoginResponse {
return apiInterface?.makeLoginCall(loginRequest)
}
}
API接口(interface).kt
suspend fun makeLoginCall(loginRequest): LoginResponse?
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
@POST("login/....")
fun loginRequest(@Body loginRequest: LoginRequest): Deferred<LoginResponse>?
我的问题是:
- 我的方法在架构上是否正确?
- 如何在我的代码中传递 http 错误代码或没有互联网连接
- 我的解决方案还有更好的方法吗?
最佳答案
在本地范围内启动协程是一个很好的做法,它可以在生命周期感知类中实现,例如 Presenter 或 ViewModel。您可以使用下一种方法来传递数据:
在单独的文件中创建
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
:suspend fun onUserLogin(loginRequest: LoginRequest): Result<LoginResponse> { return apiInterface.makeLoginCall(loginRequest) }
将
APIInterface
和APIInterfaceImpl
中的makeLoginCall
函数修改为如下代码: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
使用下一个代码: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
表达式:
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 */ }
}
}
关于android - Kotlin 协程处理错误和实现,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54077592/