Search code examples
androidandroid-architecture-componentsandroid-livedatamutablelivedata

Android - LiveData doesn't get updated


In my fragment I observe dbQuestionsList field:

viewModel.dbQuestionsList.observe(viewLifecycleOwner, Observer { list ->
            Log.i("a", "dbQuestionsList inside fragment = $list ")
        })

In my fragment I have few buttons and depending on which one is pressed I call method on viewModel passing the string which was set as tag to the button.

viewModel.onFilterChanged(button.tag as String)

My ViewMode:

   lateinit var dbQuestionsList: LiveData<List<DatabaseQuestion>>
   init{
    onFilterChanged("") 
   }
   private fun onFilterChanged(filter: String) {
                dbQuestionsList = mRepository.getDbQuestionsForCategory(filter)
   }

Repository method:

fun getDbQuestionsForCategory(categoryName: String): LiveData<List<DatabaseQuestion>> {
        return database.dbQuestionsDao().getDbQuestionsByCategory(categoryName)
    }

Dao method:

@Query("SELECT * FROM db_questions_database WHERE category = :categoryId")
    fun getDbQuestionsByCategory(categoryId: String): LiveData<List<DatabaseQuestion>>

When I press button, viewModel method is called with argument which should be used to update LiveData by searching through room database, but NOTHING gets updated for no reason. Database is not empty so there is no reason to return null and not trigger observer in main Fragment. But when I do this in my viewModel:

lateinit var dbQuestionsList: LiveData<List<DatabaseQuestion>>
       init{
        onFilterChanged("travel") 
       }

where I hardcode parameter, the room will return list and observer in fragment will be triggered, so it works like that but doesn't work when arguments is passed when button is pressed, Please explain because this thing doesn't make sense. I tried with mutable live data, with using .setValue and .postValue but NOTHING works.


Solution

  • The reason you aren't getting updates is because onFilterChanged() is reassigning dbQuestionsList, not updating it. So the variable you observe initially is never actually modified.

    I would probably implement this using a Transformation:

    val filter = MutableLiveData<String>().apply { value = "" }
    val dbQuestionsList = Transformations.switchMap(filter) {
        mRepository.getDbQuestionsForCategory(filter)
    }
    

    Then in your fragment just set the filter when your button is clicked:

    viewModel.filter.value = button.tag as String