可重复使用的机制,以监听LiveData在Android中的特定错误



我已经通过改造与后端进行了集成。我的项目架构与谷歌提出的GithubBrowserSample类似。这意味着,我的ViewModel有一些可以观察到的LiveData

任何请求都可以抛出";401未经授权";我想重定向到登录片段。在观察的过程中,我可以在检查碎片错误的细节时做到这一点

viewModel.user.observe(viewLifecycleOwner, { response ->
if (response.status == Status.SUCCESS) {
// do work there
} else if (response.status == Status.ERROR) {
// check does this 401 and redirect
}
})

但是,我的应用程序中有很多这样的地方,我需要一些机制用于监听401和重定向,该重定向可以应用于开箱即用的所有位置,而无需检查每个位置的

比方说,一些包装器,一些重复使用的utils检查特定的错误

创建一个基类,创建一个扩展AppCompactActivity的类意味着基类将是一个Parent活动并监听用户。在那里观察并用父活动扩展当前活动:

class parentActivity extends AppCompactActivity() {
onCreate(){
////Listener for the observer here 
this.user.obser{
} 
} 
}
//////////////////////////
class yourActivity extends parentActivity(){
//TODO your code
}

这可能不会限制您需要进行的检查,但它将逻辑从"活动"移动到ViewModel(在那里可以更容易地进行测试(。

在您的ViewModel中

val user: LiveData<Result<User>> = repository.getUser() // put your actual source of fetching the user here
val needsRedirectToLogin: LiveData<Boolean> = Transformations.map(user) { response ->
response.code == 401
}

改进:你可以为此创建一个扩展函数,你可以在其他ViewModel中重复使用相同的场景:

/**
* Returns true when [code] matches the Response code.
*/
fun LiveData<Response<Any>>.isErrorCode(code: Int): LiveData<Boolean> = Transformations.map(this) { response ->
response.code == code
}

然后像这样使用:

val needsRedirectToLogin: LiveData<Boolean> = user.isErrorCode(401)

在您的片段中:

viewModel.needsRedirectToLogin.observe(viewLifecycleOwner, { redirectToLoginPage ->
if (redirectToLoginPage) { 
// do the redirect here.
}

下一步可能是使用EventBus或BroadcastReceiver发送此事件。所以你只有一个地方可以处理这个问题。

从这里开始有很多方法(取决于您的要求(。但我希望这能给你一个想法,并对你有所帮助。

如果要处理的错误特定于401 Unauthorized,则可以实现Authenticator并将其附加到okhttp

首先,创建您的Authenticator

class YourAuthenticator : Authenticator {
// This callback is only called when you got 401 Unauthorized response
override fun authenticate(route: Route?, response: Response): Request? {
// Navigate to Login fragment
}
}

然后,将Authenticator添加到您的okhttp生成器中

val yourAuthenticator = YourAuthenticator()
val okHttp = OkHttpClient.Builder()
.authenticator(yourAuthenticator)
.build()

最新更新