I am using the new paging library for my data. Everything works fine when the ViewModel is created and live data is first initialized. Problem is that I can not update the value of my live data when for example I click on menu Item and want to update it with a different set of data. Then onChanged method in my fragment does not get called. I have read about MutableLiveData and methods like setValue and postValue which can update the live data, but in my case, I am using LivePagedListProvider and cannot return MutableLiveData from a database.
Dao:
@Query("SELECT * FROM teams ORDER BY name ASC")
LivePagedListProvider<Integer, Team> getAllTeams();
Fragment:
mTeamViewModel.mTeamsList.observe(this, new Observer<PagedList<Team>>() {
@Override
public void onChanged(@Nullable PagedList<Team> teams) {
mTeamAdapter.setList(teams);
}
});
ViewModel:
public LiveData<PagedList<Team>> mTeamsList;
@Inject
DatabaseManager mDatabaseManager;
void setTeamViewModel(final DatabaseManager databaseManager) {
mDatabaseManager = databaseManager;
mTeamsList = mDatabaseManager.getAllTeams().create(
0,
new PagedList.Config.Builder()
.setPageSize(50)
.setPrefetchDistance(50)
.setEnablePlaceholders(true)
.build());
}
boolean onOptionsItemSelected(final MenuItem item) {
switch (item.getItemId()) {
case R.id.action_favorite:
mTeamsList = mDatabaseManager.getFavoriteTeams().create(
0,
new PagedList.Config.Builder()
.setPageSize(50)
.setPrefetchDistance(50)
.build());
return true;
default: return false;
}
}
Finally I found the solution after the struggle of 3 days,
For updating the value of LiveData<PagedList>
we can use MediatorLiveData
, as follows, inside your ViewModel
class:
public LiveData<PagedList<RecipeListPojo>> liveData;
private MediatorLiveData<PagedList<RecipeListPojo>> mediatorLiveData;
public RecipeListViewModel(@NonNull Application application) {
super(application);
mediatorLiveData = new MediatorLiveData<>();
}
public MediatorLiveData<PagedList<RecipeListPojo>> init(RecipeDao recipeDao, RecipeFrom recipeFrom, String orderBy) {
liveData = new LivePagedListBuilder(recipeDao.getAllRecipesList(simpleSQLiteQuery), 6).build();
mediatorLiveData.addSource(liveData, new Observer<PagedList<RecipeListPojo>>() {
@Override
public void onChanged(@Nullable PagedList<RecipeListPojo> recipeListPojos) {
mediatorLiveData.setValue(recipeListPojos);
}
});
return mediatorLiveData;
}
Further details can be found here about MediatorLiveData
Create a isFavourite
column in your model. Then:
@Query("SELECT * FROM teams WHERE isFavourite = true")
LivePagedListProvider<Integer, Team> getFavouriteTeams();
Then you should have a ViewModel
with a function/field that returns a MutableLiveData<PagedList<Team>>
and in the Fragment
/Activity
you observe to that field. In your Fragment
/Activity
you tell the ViewModel
every change you need to do to de list showed. Then in the ViewModel
you assign different values to the live data list.
Transformations.switchMap can help: https://developer.android.com/reference/android/arch/lifecycle/Transformations#switchmap
class SearchViewModel() : ViewModel(){
val teamId = MutableLiveData<Int>()
var teamsList: LiveData<PagedList<Team>>=
Transformations.switchMap(teamId) { id ->
//just example
if (id <= 0) {
//1
searchDbManager.searchWithoutId()
} else {
//2
anotherSearchDbManager.searchWithId(id)
}.setBoundaryCallback(SearchResultBoundaryCallback()).build()
}
}
fun changeTeamId(id : Int){
teamId.postValue(id)
}
If you want to change the search process to search with team ID (or switch to another datasource), just call from Fragment:
viewModel.changeTeamId(2)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With