每次从活动和发出以前的数据中观察到 LIveData 两次以上
LIveData is observed more than twice everytime from acivity and emitting previous data
我遵循 MVVM 登录 API,使用 Retrofit,我的问题是 livedata 被观察了两次以上,并且在从 activity 观察时总是发出先前的响应,但是在 Repository 中它给出了正确的响应
我尝试了很多来自 Whosebug 和其他网站的解决方案,但仍然没有运气,也尝试删除观察者但仍然获得以前的数据,所以请提出一个可行的解决方案,我将 post 下面的代码,
LoginActivity.kt
private lateinit var loginViewModel: LoginViewModel
loginViewModel = ViewModelProvider(this, ViewModelProvider.NewInstanceFactory()).get(
LoginViewModel::class.java
)
loginViewModel.login(userEmail, pwd)
loginViewModel.getLoginRepository().observe(this, Observer {
val loginResult = it ?: return@Observer
val accessToken = loginResult.user?.jwtToken.toString()
})
val statusMsgObserver = Observer<String> { statusMsg ->
showToast(statusMsg)
})
val errorMsgObserver = Observer<String> { errorMsg ->
// Update the UI
showToast(errorMsg)
})
loginViewModel.getStatusMessage()?.observe(this, statusMsgObserver)
loginViewModel.getErrorStatusMessage()?.observe(this, errorMsgObserver)
LoginViewModel.kt:
class LoginViewModel: ViewModel() {
private var loginRepository: LoginRepository? = null
private var _mutableLiveData = MutableLiveData<LoginAPIResponse?>()
val liveData: LiveData<LoginAPIResponse?> get() = _mutableLiveData
private var responseMsgLiveData:MutableLiveData<String>?= null
private var errorResponseMsgLiveData:MutableLiveData<String>?= null
fun login(username: String, password: String) {
loginRepository = LoginRepository.getInstance()!!
/* Query data from Repository */
//val _mutableLiveData: MutableLiveData<Response<LoginAPIResponse?>?>? = loginRepository?.doLogin(username, password)
_mutableLiveData = loginRepository?.doLogin(username, password)!!
responseMsgLiveData = loginRepository?.respMessage!!
errorResponseMsgLiveData = loginRepository?.loginResponseErrorData!!
}
fun getLoginRepository(): LiveData<LoginAPIResponse?> {
return liveData
}
fun getStatusMessage(): LiveData<String>? {
return responseMsgLiveData
}
fun getErrorStatusMessage(): LiveData<String>? {
return errorResponseMsgLiveData
}
}
LoginRepository.kt:
class LoginRepository {
private val loginApi: ApiEndpoints = RetrofitService.createService(ApiEndpoints::class.java)
val responseData = MutableLiveData<LoginAPIResponse?>()
var respMessage = MutableLiveData<String>()
var loginResponseErrorData = MutableLiveData<String>()
fun doLogin(username: String, password: String)
: MutableLiveData<LoginAPIResponse?> {
respMessage.value = null
loginResponseErrorData.value = null
val params = JsonObject()
params.addProperty("email", username)
params.addProperty("password",password)
val jsonParams = JsonObject()
jsonParams.add("user",params)
loginApi.loginToServer(jsonParams).enqueue(object : Callback<LoginAPIResponse?> {
override fun onResponse( call: Call<LoginAPIResponse?>, response: Response<LoginAPIResponse?> ) {
responseData.value = response.body()
respMessage.value = RetrofitService.handleError(response.code())
val error = response.errorBody()
if (!response.isSuccessful) {
val errorMsg = error?.charStream()?.readText()
println("Error Message: $errorMsg")
loginResponseErrorData.value = errorMsg
} else {
println("API Success -> Login, $username, ${response.body()?.user?.email.toString()}")
}
}
override fun onFailure(call: Call<LoginAPIResponse?>, t: Throwable) {
println("onFailure:(message) "+t.message)
loginResponseErrorData.value = t.message
responseData.value = null
}
})
return responseData
}
companion object {
private var loginRepository: LoginRepository? = null
internal fun getInstance(): LoginRepository? {
if (loginRepository == null) {
loginRepository = LoginRepository()
}
return loginRepository
}
}
}
在onDestroy()中,我已经移除了观察者,
override fun onDestroy() {
super.onDestroy()
loginViewModel.getLoginRepository()?.removeObservers(this)
this.viewModelStore.clear()
}
在 LoginActivity 中,当我观察 loginResult 时,它首先给出先前发出的 accessToken,然后再次调用并给出当前的 accessToken,类似地观察者每次被调用两次以上。
但是在存储库中,它提供了最近的数据,请检查我的代码并建议我必须在哪里更正才能获得正确的最近实时数据
终于找到解决办法了,在LoginRepository中,我在doLogin()外声明了responseData,应该在doLogin()内声明
由于它在方法之外,它总是先给出以前的数据,然后再给出当前数据,
一旦我声明内部方法问题就解决了,现在它工作完美!!!
我遵循 MVVM 登录 API,使用 Retrofit,我的问题是 livedata 被观察了两次以上,并且在从 activity 观察时总是发出先前的响应,但是在 Repository 中它给出了正确的响应 我尝试了很多来自 Whosebug 和其他网站的解决方案,但仍然没有运气,也尝试删除观察者但仍然获得以前的数据,所以请提出一个可行的解决方案,我将 post 下面的代码,
LoginActivity.kt
private lateinit var loginViewModel: LoginViewModel
loginViewModel = ViewModelProvider(this, ViewModelProvider.NewInstanceFactory()).get(
LoginViewModel::class.java
)
loginViewModel.login(userEmail, pwd)
loginViewModel.getLoginRepository().observe(this, Observer {
val loginResult = it ?: return@Observer
val accessToken = loginResult.user?.jwtToken.toString()
})
val statusMsgObserver = Observer<String> { statusMsg ->
showToast(statusMsg)
})
val errorMsgObserver = Observer<String> { errorMsg ->
// Update the UI
showToast(errorMsg)
})
loginViewModel.getStatusMessage()?.observe(this, statusMsgObserver)
loginViewModel.getErrorStatusMessage()?.observe(this, errorMsgObserver)
LoginViewModel.kt:
class LoginViewModel: ViewModel() {
private var loginRepository: LoginRepository? = null
private var _mutableLiveData = MutableLiveData<LoginAPIResponse?>()
val liveData: LiveData<LoginAPIResponse?> get() = _mutableLiveData
private var responseMsgLiveData:MutableLiveData<String>?= null
private var errorResponseMsgLiveData:MutableLiveData<String>?= null
fun login(username: String, password: String) {
loginRepository = LoginRepository.getInstance()!!
/* Query data from Repository */
//val _mutableLiveData: MutableLiveData<Response<LoginAPIResponse?>?>? = loginRepository?.doLogin(username, password)
_mutableLiveData = loginRepository?.doLogin(username, password)!!
responseMsgLiveData = loginRepository?.respMessage!!
errorResponseMsgLiveData = loginRepository?.loginResponseErrorData!!
}
fun getLoginRepository(): LiveData<LoginAPIResponse?> {
return liveData
}
fun getStatusMessage(): LiveData<String>? {
return responseMsgLiveData
}
fun getErrorStatusMessage(): LiveData<String>? {
return errorResponseMsgLiveData
}
}
LoginRepository.kt:
class LoginRepository {
private val loginApi: ApiEndpoints = RetrofitService.createService(ApiEndpoints::class.java)
val responseData = MutableLiveData<LoginAPIResponse?>()
var respMessage = MutableLiveData<String>()
var loginResponseErrorData = MutableLiveData<String>()
fun doLogin(username: String, password: String)
: MutableLiveData<LoginAPIResponse?> {
respMessage.value = null
loginResponseErrorData.value = null
val params = JsonObject()
params.addProperty("email", username)
params.addProperty("password",password)
val jsonParams = JsonObject()
jsonParams.add("user",params)
loginApi.loginToServer(jsonParams).enqueue(object : Callback<LoginAPIResponse?> {
override fun onResponse( call: Call<LoginAPIResponse?>, response: Response<LoginAPIResponse?> ) {
responseData.value = response.body()
respMessage.value = RetrofitService.handleError(response.code())
val error = response.errorBody()
if (!response.isSuccessful) {
val errorMsg = error?.charStream()?.readText()
println("Error Message: $errorMsg")
loginResponseErrorData.value = errorMsg
} else {
println("API Success -> Login, $username, ${response.body()?.user?.email.toString()}")
}
}
override fun onFailure(call: Call<LoginAPIResponse?>, t: Throwable) {
println("onFailure:(message) "+t.message)
loginResponseErrorData.value = t.message
responseData.value = null
}
})
return responseData
}
companion object {
private var loginRepository: LoginRepository? = null
internal fun getInstance(): LoginRepository? {
if (loginRepository == null) {
loginRepository = LoginRepository()
}
return loginRepository
}
}
}
在onDestroy()中,我已经移除了观察者,
override fun onDestroy() {
super.onDestroy()
loginViewModel.getLoginRepository()?.removeObservers(this)
this.viewModelStore.clear()
}
在 LoginActivity 中,当我观察 loginResult 时,它首先给出先前发出的 accessToken,然后再次调用并给出当前的 accessToken,类似地观察者每次被调用两次以上。 但是在存储库中,它提供了最近的数据,请检查我的代码并建议我必须在哪里更正才能获得正确的最近实时数据
终于找到解决办法了,在LoginRepository中,我在doLogin()外声明了responseData,应该在doLogin()内声明 由于它在方法之外,它总是先给出以前的数据,然后再给出当前数据, 一旦我声明内部方法问题就解决了,现在它工作完美!!!