Search code examples
androidkotlinandroid-livedataandroid-viewmodelandroid-architecture-navigation

How to share data between an activity and a fragment using a SharedViewModel?


I have an activity class where I have added a fragment using Navigation Components. I have added an OnAuthStateChangeListener in my activity to see when the user is sign-out or not. I have implemented the method like so:

override fun onAuthStateChanged(isUserSignedOut: Boolean) {
    if (!isUserSignedOut) {
        sharedViewModel.setUid(uid)
    }
}

My SharedViewModel class looks like so:

class SharedViewModel @Inject constructor(): ViewModel() {
    val liveData = MutableLiveData<String>()

    fun setUid(uid: String) {
        liveData.value = uid
    }
}

Now in my fragment, I tried to get the uid like so:

override fun onActivityCreated(savedInstanceState: Bundle?) {
    super.onActivityCreated(savedInstanceState)
    sharedViewModel.liveData.observe(viewLifecycleOwner, Observer<String> { uid ->
        logErrorMessage("uid: $uid")
    })
}

But that observer never fires. I have no output in the logcat whatsoever. How can I get that uid correctly?


Solution

  • So after a long discussion,

    This happens because the instance of sharedViewModel in both Activity and Fragment are different.

    You need to add @Singleton annotation to the way you provide it with Dagger, like this

    @Module
    abstract class AppViewModelModule {
    @Singleton
    @Binds
    abstract fun bindAppViewModelFactory(factory: AppViewModelFactory?): ViewModelProvider.Factory?
    
    @Singleton
    @Binds
    @IntoMap
    @ViewModelKey(SharedViewModel::class)
    abstract fun provideSharedViewModel(viewModel: SharedViewModel?): ViewModel?
    }
    

    Also, add @Singleton annotation to SharedViewModel class too, like this

    @Singleton
    class SharedViewModel @Inject constructor(): ViewModel() {
        val liveData = MutableLiveData<String>()
    
        fun setUid(uid: String) {
            liveData.value = uid
        }
    }
    

    Glad this helped you :)