14

I decided to teach myself Java and Android by doing a simple database app. I already implemented some functionality the "lazy" way - all selects are done on the main thread.

Now I want to use LiveData for selects. I've read the simplistic training guide on android developers and implemented a more complex solution from codelabs guide, with LiveData and RecyclerView. Inserts, updates, deletes, and selects for whole tables work flawlessly, however I have no idea how to pass parameters to selects.

Example: I have an activity with scrollable list of all records and I want to apply some filters to the list (search). From what I understand the actual select method from DAO is called only once (when ViewModel is created), so how do I update query with new parameters?

Other example: I have other activity that displays all columns of a record (for viewing and editing). How do I pass id to query to select a single row?

My database code is more less the same as in this codelab

Edit: I finally did it like that: every time I want to update query parameters I call select from DAO (through ViewModel and Repo) and add a new observer to that new list. This solution doesn't seem optimal but I guess it works...

Gunnar Bernstein
  • 6,074
  • 2
  • 45
  • 67
Sancho
  • 220
  • 2
  • 9

1 Answers1

36

I think your solution is a Transformations.switchMap. The simplest example how it may works in the case from codelab

public class WordViewModel extends AndroidViewModel {
    private WordRepository mRepository;
    private LiveData<List<Word>> mAllWords;
    private LiveData<List<Word>> searchByLiveData;
    private MutableLiveData<String> filterLiveData = new MutableLiveData<>();

    public WordViewModel (Application application) {
        super(application);
        mRepository = new WordRepository(application);
        mAllWords = mRepository.getAllWords();
        searchByLiveData = Transformations.switchMap(filterLiveData, 
                                                     v -> mRepository.searchBy(v));
    }

    LiveData<List<Word>> getSearchBy() { return searchByLiveData; }
    void setFilter(String filter) { filterLiveData.setValue(filter); }
    LiveData<List<Word>> getAllWords() { return mAllWords; }
    public void insert(Word word) { mRepository.insert(word); }
}

So, when you set filter value, it will change value of searchByLiveData

I hope this helps you.

Riot Goes Woof
  • 3,504
  • 5
  • 20
  • 35
basilkot
  • 592
  • 6
  • 15
  • Finally got some time to try your solution and it works wonderfully! Thank you so much! That's exactly what I was looking for. – Sancho Apr 26 '18 at 13:29
  • In repository.searchBy(v) it must be **mRepository**? – mjn42 Nov 07 '18 at 13:39
  • 1
    @mjn42 yes, i fix it. regarding the error, show me the code and perhaps i will be able to help you – basilkot Nov 07 '18 at 17:13
  • in the line void setFilter(String filter) { filterLiveData.value = filter; } the ".value" does not exist in filterLiveData – mjn42 Nov 08 '18 at 10:38
  • 1
    @mjn42 setValue, sure – basilkot Nov 08 '18 at 11:06
  • @basilkot it was helpful for me where I had to fetch data from Room based on various sort options selected by the user. Earlier, I was doing it in a very unusual way. Thanks! – Shahood ul Hassan Feb 10 '19 at 06:57
  • Thank you very much! This has resolved a fair bit of headache for me :) – Adi B Mar 26 '19 at 21:16
  • 2
    Your code helped a lot. But there is a problem in the line : `private LiveData filterColor = new MutableLiveData();`instead use `private MutableLiveData filterColor = new MutableLiveData(); `because the **LiveData's** `setValue()` has a protected access while **MutableLiveData's** `setValue()` has a public access. – Sayok Majumder May 31 '19 at 08:00
  • 2
    have save mylife – QuestionAndroid Jun 07 '19 at 09:46