LiveData + ViewModel + Room: Предоставление LiveData, возвращаемого запросом, который изменяется с течением времени (через поиск fts) - PullRequest
3 голосов
/ 10 ноября 2019

У меня есть запрос FTS в моем DAO, который я хотел бы использовать для поиска в моем приложении. Действие передает запрос на просмотр модели каждый раз, когда изменяется текст поиска.

Проблема в том, что Room возвращает LiveData каждый раз, когда выполняется запрос, в то время как я хотел бы обновить тот же объект LiveData, когда я запускаю запрос.

Я думал о копировании данных из LiveData, какая комната возвращается в мою dataSet (см. Код ниже) . Это был бы хороший подход? (И если да, то как бы я на самом деле это сделал?)

Вот моя работа на данный момент:

В моей деятельности:

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
        }
    }
}

Репозиторий:


    //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>
}

1 Ответ

2 голосов
/ 10 ноября 2019
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
}
...