Initialize LiveData In AndroidViewModel

Ved Agarwal picture Ved Agarwal · Dec 31, 2017 · Viewed 9.3k times · Source

I am looking for a way to initialize the LiveData object inside the ViewModel. Items are currently only getting initialized when setQuery method is called from the activity.

public class MyListViewModel extends AndroidViewModel {

private final LiveData <List<Item>> items;
private final MutableLiveData<String> query = new MutableLiveData<>();


private MyDatabase db;

public MyListViewModel(Application application) {
    super(application);
    db  = MyDatabase.getInstance(application);
    items = Transformations.switchMap(query, (search)->{
        if (search == null || search.trim().length() == 0) {
            return db.itemDao().getAllItems();
        } else {
            return db.itemDao().findItemsBySearchTerm(search);
        }
    });

}

public LiveData<List<Item>> getItems() {
    return items;
}

public void setQuery(String queryText) {
   query.setValue(queryText);
}

}

Answer

adityakamble49 picture adityakamble49 · Jan 1, 2018

You have to call setQuery(String queryText) at least once As per Transformation documentation

The transformations aren't calculated unless an observer is observing the returned LiveData object. Because the transformations are calculated lazily, lifecycle-related behavior is implicitly passed down without requiring additional explicit calls or dependencies.

So that if you don't call setQuery(String queryText) from Activity it will not update MutableLiveData<String> query and will not trigger the Transformation.

If you want to avoid initial call from Activity you can call it below the Transformation initialization like this,

public MyListViewModel(Application application) {
    super(application);
    db  = MyDatabase.getInstance(application);
    items = Transformations.switchMap(query, (search)->{
        if (search == null || search.trim().length() == 0) {
            return db.itemDao().getAllItems();
        } else {
            return db.itemDao().findItemsBySearchTerm(search);
        }
    });
    setQuery("")
}

It will trigger the empty search part and will return All Items.

Also you need to observe the returned data in your case items. If no observer is observing the data then Transaction will not trigger.

As I referred from Documentation and few Blogs this worked for me