Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to update LiveData value?

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;
    }
}
like image 529
tomas Avatar asked Nov 16 '17 16:11

tomas


3 Answers

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

like image 175
Anushka Khare Avatar answered Oct 15 '22 09:10

Anushka Khare


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.

like image 39
Damia Fuentes Avatar answered Oct 15 '22 09:10

Damia Fuentes


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)
like image 31
jno Avatar answered Oct 15 '22 09:10

jno