Reputation: 33
Is it possible to get specific rows from Room with LiveData? My goal is to retrieve certain items from data base, when each item is conditioned by to columns ("page" and "category"). The problem is that in LiveData observer I always receive the same page - that livedata object had been initiated with it in the beginning. It has no effect if I change it afterwards in the ViewModel:
private fun requestNextPageFromDB(page: Int) {
filmsListLiveData = interactor.getPageOfFilmsFromDB(page)
}
I create the LiveData object in init block of my ViewModel:
var filmsListLiveData: LiveData<List<Film>>
init {
filmsListLiveData = interactor.getPageOfFilmsFromDB(2)
The method in Interactor class I initiate the livedata object:
fun getPageOfFilmsFromDB(page: Int): LiveData<List<Film>> =
repo.getPageOfFilmsInCategoryFromDB(page, getFilmsCategoryFromPreferences())
Next method in the repository:
fun getPageOfFilmsInCategoryFromDB(page: Int, category: String): LiveData<List<Film>> {
return filmDao.getCachedFilmsByPageAndCategory(page, category)
}
And the last one in the Dao Intertface:
@Query("SELECT * FROM cached_films WHERE page=:requestedPage AND category=:requestedCategory")
fun getCachedFilmsByPageAndCategory(requestedPage: Int, requestedCategory:String): LiveData<List<Film>>
All the methods above are invoked properly when the page number changes in livedata object.
Thanks a lot in advance.
Upvotes: 2
Views: 291
Reputation: 6589
From the description it seems that you are just replacing the filmsListLiveData
reference, however the observer remains the original one, that is why it is not notified about any changes, since in the original filmsListLiveData
there have been no changes.
You can use a MutableLiveData
for the page value and then a Transformations.switchMap
to obtain a LiveData that will react to the changes of the page value.
Inside your ViewModel, you can do something like this
// starting page is 2, not sure if it should be 1 or 2, I just copied you logic from init
private val currentPageLiveData = MutableLiveData(2)
var filmsListLiveData = Transformations.switchMap(currentPageLiveData) { page ->
interactor.getPageOfFilmsFromDB(page)
}
private fun requestNextPageFromDB(page: Int) {
currentPageLiveData.value = page
}
init {
// not needed anymore - remove this code
// filmsListLiveData = interactor.getPageOfFilmsFromDB(2)
}
With that, every time requestNextPageFromDB(page: Int)
will be called, currentPageLiveData
value will change, the switchMap
will get called and a new call to interactor.getPageOfFilmsFromDB(page)
will be made. That will update the LiveData
value and your observer will be called again.
So the switchMap
does exactly what you need, it switches the LiveData behind the scenes every time the source LiveData changes (in this case the currentPageLiveData) in such a way, that existing observers stop observing the old LiveData instance, the one switched from, and start observing the new LiveData instance, the one switched to.
At this point you can also change var filmsListLiveData
to val filmsListLiveData
and remove all code that is trying to replace its reference, since there is no need to replace this LiveData anymore (now it reacts to the page value change on its own).
Upvotes: 1