Ivan Patrice
Ivan Patrice

Reputation: 129

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?

Upvotes: 0

Views: 121

Answers (1)

Franz Andel
Franz Andel

Reputation: 1711

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 :)

Upvotes: 1

Related Questions