Reputation: 6795
I'm trying to retry the logic of getting data from Firebase, what my app does is the follow.
If there is no internet connection it will trigger the Failure Resource and will show a retry button, but when I click this button, it seems that the viewmodel does not request again the data, instead is just showin my progress without requesting again the data to my repo
viewModel.getPrizes.observe(viewLifecycleOwner, Observer { it ->
when(it){
is Resource.Loading -> {
// Loading...
}
is Resource.Success -> {
hideProgress()
setArrayData(it.data)
}
is Resource.Failure -> {
hideProgress()
hidePrizes()
retry_constrain.visibility = View.VISIBLE
btn_retry.setOnClickListener{
viewModel.getPrizes
showProgress()
retry_constrain.visibility = View.GONE
}
Toast.makeText(
requireContext(),
"An error has ocourred:${it.throwable.message}",
Toast.LENGTH_SHORT
).show()
}
}
})
What I spect here is in my Resource.Failure to request again the data after pressing my btn_retry
but instead, it only shows my progress bar and nothing happens
class PrizesViewModel(private val useCase:IPrizes): ViewModel() {
val getPrizes = liveData(Dispatchers.IO) {
emit(Resource.Loading())
try{
val prizes = useCase.fetchPrizes()
emit(prizes)
}catch (e:Exception){
Crashlytics.logException(e.cause)
emit(Resource.Failure(e.cause!!))
}
}
}
Why is not re-fetching my values after calling again viewModel.getPrizes
in my Resource.Failure
?
Upvotes: 0
Views: 1203
Reputation: 6795
What I ended up doing was a Transformation, since a Transformation can be triggered whenever the mutable value changes, I can retry the whole coroutine doing so
private val shouldRetry = MutableLiveData<Boolean>()
val fetchPrizes: LiveData<Resource<Prizes>> = Transformations.switchMap(shouldRetry) {
liveData(context = viewModelScope.coroutineContext + Dispatchers.IO) {
emit(Resource.Loading())
try{
val prizes = useCase.fetchPrizes()
emit(prizes)
}catch (e:Exception){
Crashlytics.logException(e.cause)
emit(Resource.Failure(e.cause!!))
}
}
}
fun retryData(retry: Boolean) {
shouldRetry.value = retry
}
Then from my UI I just call viewModel.retryData(true)
whenever I want
Upvotes: 0
Reputation: 13223
The LiveData
from the second call to viewModel.getPrizes
has no Observers
attached to it, and hence it will not get a value until there is one.
You would have to call viewModel.getPrizes.observe(...)
again inside the current Observer
which is not optimal.
You will have to rethink your design a bit so you can trigger a new call to useCase.fetchPrizes()
and still get the new value by observing the original LiveData
.
Upvotes: 2