It Is Ok To Call ObserveForever() On Livedata Returned By Transformations.map() Inside ViewModel?
I tried to use LiveData Transformations.map() to check the result and update the UI. But Transformations.map() callback not triggered without an observer.
So is it good way to call observeForever {}
on livedata returned by Tranformations.map? And remove obervers on onCleared on ViewModel?
private lateinit var map: LiveData<Unit>
fun getAppConfiguration(): MutableLiveData<TopRatedMoviesResponse> {
progressDialogVisibleLiveData.postValue(true)
val appConfigurationLiveData = MutableLiveData<TopRatedMoviesResponse>()
val appConfigurationSourceLiveData : MutableLiveData<DataResult> = splashScreenRepository.getAppConfiguration(getApplication())
map = Transformations.map(appConfigurationSourceLiveData) { dataResult ->
progressDialogVisibleLiveData.postValue(false)
when (dataResult) {
is DataResultSuccess -> {
appConfigurationLiveData.postValue(dataResult.data as TopRatedMoviesResponse)
}
is DataResultFailed -> {
when (dataResult.errorCode) {
HTTPError.NO_INTERNET -> {
errorDialogVisibleLiveData.postValue(dataResult)
}
HTTPError.BAD_REQUEST -> {
errorDialogVisibleLiveData.postValue(dataResult)
}
HTTPError.UNAUTHORISED -> {
unAuthorisedEventLiveData.postValue(true)
}
HTTPError.FORBIDDEN, HTTPError.NOT_FOUND, HTTPError.INTERNAL_SERVER_ERROR, HTTPError.UNKNOWN -> {
errorDialogVisibleLiveData.postValue(dataResult)
}
}
}
}
}
map.observeForever { }
return appConfigurationLiveData
}
override fun onCleared() {
super.onCleared()
map.removeObserver { }
}
Answer
But Transformations.map callback not triggered without observer.
It's normal, without the call to observerForever() the LiveData returned by Transformations.map() doesn't have anyone to offer the data that it holds.
So is it good way to call observeForever {} on livedata returned by Tranformations.map?
Looking at what you do in that method the answer is no, that's not how you use Transformations.map(). The goal of that method is to apply some changes to the values emitted by the source LiveData before those value are presented to an observer. In your case you want a simple type change(from dataResult.data to TopRatedMoviesResponse) along with triggering some error LiveDatas when something went wrong. Check the code below:
fun getAppConfiguration(): MutableLiveData<TopRatedMoviesResponse> {
progressDialogVisibleLiveData.postValue(true)
val appConfigurationSourceLiveData : MutableLiveData<DataResult> = splashScreenRepository.getAppConfiguration(getApplication())
return Transformations.map(appConfigurationSourceLiveData) { dataResult ->
progressDialogVisibleLiveData.postValue(false)
when (dataResult) {
is DataResultSuccess -> {
dataResult.data as TopRatedMoviesResponse
}
is DataResultFailed -> {
when (dataResult.errorCode) {
HTTPError.UNAUTHORISED -> {
unAuthorisedEventLiveData.postValue(true)
}
HTTPError.FORBIDDEN, HTTPError.NOT_FOUND, HTTPError.INTERNAL_SERVER_ERROR, HTTPError.UNKNOWN, HTTPError.NO_INTERNET, HTTPError.BAD_REQUEST -> {
errorDialogVisibleLiveData.postValue(dataResult)
}
}
// we have to return something even if an error occured
// I'm returning null, your UI should handle this
null
}
}
}
}
Also have a look at the architecture guide for alternative ways of handling data and errors with LiveData.
Related Questions
- → should I choose reactjs+f7 or f7+vue.js?
- → Phonegap Android write to sd card
- → Local reference jquery script in nanohttpd (Android)
- → Click to navigate on mobile devices
- → How to allow api access to android or ios app only(laravel)?
- → Access the Camera and CameraRoll on Android using React Native?
- → React native change listening port
- → What is the default unit of style in React Native?
- → Google play market autocomplete icon
- → Warning: Each child in an array or iterator should have a unique "key" prop. Check the render method of `ListView`
- → Using Laravel with Genymotion
- → react native using like web-based ajax function
- → react native pdf View