Search code examples
androidkotlinmutablelivedata

Unable to observe livedata set in viewmodel from activity


I am a newbie Android developer, and I am trying to observe a boolean set in the ViewModel from its parent's activity. I can observe its initial state as soon as the app launches, but any change applied later on doesn't seem to trigger the observer (i.e. when I switch the fragments).

Here is the code for my ViewModel:

class MyMusicViewModel  : ViewModel() {


    private var _MyMusicViewOn = MutableLiveData<Boolean>()
    val MyMusicViewOn: LiveData<Boolean> get() = _MyMusicViewOn



    init {
        Timber.i("MyMusicViewModel Init Called!")
        setMyMusicView(true)
    }

    override fun onCleared() {
        super.onCleared()
        Timber.i("MyMusicViewModel Cleared!")
        setMyMusicView(false)
    }


    fun setMyMusicView(setter: Boolean) {
        Timber.i("MyMusicViewModel setter called! %s", setter)
        _MyMusicViewOn.value = setter
    }


}

And here is its parent's activity:

class FullscreenActivity : AppCompatActivity() {


    private val viewModel: MyMusicViewModel by viewModels()

  
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

       
        viewModel.MyMusicViewOn.observe(this, Observer { MyMusicViewOn ->
            Timber.i("Observer called for MyMusicViewOn %s", MyMusicViewOn)
        })

    }

}

And in case you wanna see the ViewModel's related fragment, here it is:

class MyMusicFragment : Fragment() {

    private lateinit var viewModel: MyMusicViewModel

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        // Inflate the layout for this fragment
        val binding = DataBindingUtil.inflate<FragmentMyMusicBinding>(
            inflater,
            R.layout.fragment_my_music,
            container,
            false
        )
        
        viewModel = ViewModelProvider(this).get(MyMusicViewModel::class.java)

        return binding.root
    }
    

    override fun onResume() {
        super.onResume()

        Timber.i("MyMusicViewFragment resumed!")
        viewModel.setMyMusicView(true)

    }




}

What I am trying to accomplish is to observe the onResume(), onCleared() and init{} functions whenever they are called by changing the status of the MyMusicViewOn MutableLiveData Boolean. What I don't understand is why that boolean doesn't trigger the observer set in the parent activity whenever it changes.

Thankyou in advance for any thoughts!

All the best,

Fab.


Solution

  • I'm guessing that however you are populating that viewModel property in your Fragment, you are not using the Activity's ViewModel instance. The easiest way to get the same instance that the Activity is using would be to use the activityViewModels delegate:

    private val viewModel: MyMusicViewModel by activityViewModels()