I have an FTS query in my DAO which I'd like to use to provide search in my App. The activity passes the query to view model each time the search text is changed.
The problem is that, Room returns a LiveData
every single time the query is executed while I'd like to get same LiveData
object updated when I run the query.
I was thinking about copying data from the LiveData
which room returns into my dataSet
(see the code below). Would it be a good approach? (And if yes, how would I actually do that?)
Here's my work so far:
In my Activity:
override fun onCreate(savedInstanceState: Bundle?) {
//....
wordViewModel = ViewModelProviders.of(this).get(WordMinimalViewModel::class.java)
wordViewModel.dataSet.observe(this, Observer {
it?.let {mRecyclerAdapter.setWords(it)}
})
}
/* This is called everytime the text in search box is changed */
override fun onQueryTextChange(query: String?): Boolean {
//Change query on the view model
wordViewModel.searchWord(query)
return true
}
ViewModel:
private val repository :WordRepository =
WordRepository(WordDatabase.getInstance(application).wordDao())
//This is observed by MainActivity
val dataSet :LiveData<List<WordMinimal>> = repository.allWordsMinimal
//Called when search query is changed in activity
//This should reflect changes to 'dataSet'
fun searchWord(query :String?) {
if (query == null || query.isEmpty()) {
//Add all known words to dataSet, to make it like it was at the time of initiating this object
//I'm willing to copy repository.allWordsMinimal into dataSet here
} else {
val results = repository.searchWord(query)
//Copy 'results' into dataSet
}
}
}
Repository:
//Queries all words from database
val allWordsMinimal: LiveData<List<WordMinimal>> =
wordDao.getAllWords()
//Queries for word on Room using Fts
fun searchWord(query: String) :LiveData<List<WordMinimal>> =
wordDao.search("*$query*")
//Returns the model for complete word (including the definition for word)
fun getCompleteWordById(id: Int): LiveData<Word> =
wordDao.getWordById(id)
}
DAO:
interface WordDao {
/* Loads all words from the database */
@Query("SELECT rowid, word FROM entriesFts")
fun getAllWords() : LiveData<List<WordMinimal>>
/* FTS search query */
@Query("SELECT rowid, word FROM entriesFts WHERE word MATCH :query")
fun search(query :String) :LiveData<List<WordMinimal>>
/* For definition lookup */
@Query("SELECT * FROM entries WHERE id=:id")
fun getWordById(id :Int) :LiveData<Word>
}
val dataSet :LiveData<List<WordMinimal>>
val searchQuery = MutableLiveData<String>()
init {
dataSet = Transformations.switchMap(searchQuery) { query ->
if (query == null || query.length == 0) {
//return WordRepository.getAllWords()
} else {
//return WordRepository.search(query)
}
}
}
fun setSearchQuery(searchedText: String) {
searchQuery.value = searchedText
}