Livedata with a raw query getAll() : how to update liveData's data source via ui (and therefore change UI accordingly)?

from the CommonsWare Community archives

At June 27, 2019, 2:25am, root-ansh asked:

I have this Room+repository+LiveData+Viewmodel based app.
The room db consist of following classes:

@Dao
public interface TeaDao {

    @RawQuery(observedEntities = Tea.class)
    LiveData<List<Tea>> getALL(SupportSQLiteQuery query);
    ...
}

Any method which calls this function generates the query using this utility function:


// "SELECT * FROM table order by <colname>" OR
// "SELECT * FROM table where COL_FAVOURITE=1 order by <colname>"

public static SupportSQLiteQuery getSortedQuery(String sortByColname, boolean showOnlyFavorites) {

    SupportSQLiteQueryBuilder builder =
            SupportSQLiteQueryBuilder
                    .builder(DbUtils.Names.TABLE_NAME)
                    .columns(new String[]{"*"})
                    .orderBy(sortByColname);
    if (showOnlyFavorites) {
        builder.selection(Names.COL_FAVORITE + " = ? ", new Object[]{"1"});
    }

    SupportSQLiteQuery query = builder.create();
    //Log.e("DB_UTILS", "getSortedQuery:query="+query.getSql());
    return query;
}

My problem is that i couldn’t figure our how to make this structure work with my ui . See, my ui would consist of a recycler view with some menu buttons . At first, my app can show default data with no filters . I can add the observer to Livedata<List> recieved on calling getAll() from VM , and populate my recycler view in its onChanged.

But I want that when user presses a button say “show favourites” , the query Select * from table where favourites=1 is processed via getAll(), and the result of this query is automatically passed to the previously set Livedata<List> , which triggers its onChanged() and therby my ui changes to a filtered version of results.

How can i do that?


At June 27, 2019, 11:08am, mmurphy replied:

How can i do that?

As far as I know, Room does not support that.

What you can do is:

I take that approach in the ToDo sample app from Exploring Android: https://gitlab.com/commonsguy/cw-andexplore/blob/v0.7/T32-Filter/ToDo/app/src/main/java/com/commonsware/todo/ui/roster/RosterMotor.kt

Basically, you rely on Room’s automatic-updating for places where you change the database contents (e.g., insert, delete). You switch what query you are observing via the MediatorLiveData.


At June 27, 2019, 7:43pm, root-ansh replied:

I think i am getting what you are saying, sir. I read the code of RostorMotor.kt, but am currently not too good in kotlin. can you please help me with some java version of that code? (I tried decoding it to bytecode, but that got converted into some 16000 lines)


At June 27, 2019, 8:09pm, mmurphy replied:

That class uses Kotlin coroutines in the save() function, so I cannot convert it to Java in isolation.

Using the Warescription site’s full-text search, here are some chapters with Java examples of MediatorLiveData:


At June 28, 2019, 2:41am, root-ansh replied:

Thank you so much! after 3 days of pain my code is finally working :-’’’)
I am now exposing a mediator livedata<list> instead of livedata instead of livedata<list> and changing the source to a filtered query result on button click. everything is working fine and beautifully, thanks!