LaVOZs

The World’s Largest Online Community for Developers

'; android - hasActiveObservers and hasObservers false in shared ViewModel - LavOzs.Com

I'm trying to communicate between two fragments and the ViewPager2 using shared ViewModel as follows:

SharedViewModel

val viewPagerFragment = MutableLiveData<Int>()

init {
    viewPagerFragment.value = -1
}

fun displayedFragment(fragmentIndex: Int){
    viewPagerFragment.value = fragmentIndex
}

fun doSomethingForFragmentA(){
    //
}

fun doSomethingForFragmentB(){
    //
}

Fragment A

override fun onResume() {
    super.onResume()
    sharedViewModel.displayedFragment(0)
}

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    sharedViewModel = ViewModelProvider(this).get(SharedViewModel::class.java)
}

Fragment B

override fun onResume() {
    super.onResume()
    sharedViewModel.displayedFragment(1)
}

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    sharedViewModel = ViewModelProvider(this).get(SharedViewModel::class.java)
}

ViewPager2

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

    sharedViewModel.viewPagerFragment.observe(this, Observer {
        when (it) {
            0 -> sharedViewModel.doSomethingForFragmentA(it)
            1 -> sharedViewModel.doSomethingForFragmentB(it)
        }
    })

}

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    sharedViewModel = ViewModelProvider(this).get(SharedViewModel::class.java)
}

During the first call of the onActivityCreated in the ViewPager2, the LiveData Observer reacts correctly. However, both hasActiveObservers and hasObservers show false in the shared ViewModel. When I toggle from FragmentA to FragmentB, the FragmentB updates the LiveData correctly in onResume(). This time Observer in the ViewPager2 does not react to the change and the hasActiveObservers and hasObservers are still false.

It is worth mentioning that if I move observers from ViewPager to FragmentA and FragmentB everything works fine.

The only thing that comes to mind is that the ViewPager has a different host activity.

I managed to solve the issue using Channels. Not exactly what I wanted, but it works. I still hope there is a solution to the original question.

AppContainer

class AppContainer {
    val currentViewPagerFragmentChannel = Channel<Int>()
}

BaseApplication

class BaseApplication : Application(){

    val appContainer = AppContainer()
}

FragmentA

override fun onResume() {
    super.onResume()
    val app = activity?.application as BaseApplication


    GlobalScope.launch {
        app.appContainer.currentViewPagerFragmentChannel.send(0)
    }
}

FragmentB

override fun onResume() {
    super.onResume()
    val app = activity?.application as BaseApplication

    // Send an Integer
    GlobalScope.launch {
        app.appContainer.currentViewPagerFragmentChannel.send(1)
    }
}

ViewPager

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

    launch {
        val app = activity?.application as BaseApplication
        val ch = app.appContainer.currentViewPagerFragmentChannel

        if (!ch.isClosedForSend){
            for (value in ch){
                when (value) {
                    // FragmentA is displayed
                    0 -> sharedViewModel.doSomethingForFragmentA(value)
                    // FragmentB is displayed
                    1 -> sharedViewModel.doSomethingForFragmentB(value)
                }
            }
        }
    }
}
Related
What is ViewModel in MVC?
Can someone show me a simple working implementation of PagerSlidingTabStrip?
How to read Heart rate from Android Wear
Moshi's Custom Adapter with RxAndroid & Retrofit & Kotlin
Android viewModel and Kotlin: Who is the viewModel data shared with?
Problem while using multiple instance of same Fragment with same ViewModel in Viewpager
How does LiveData works in this case?
ViewModel with several LiveData and UseCases
IndexOutOfBoundsException when adding items to specific index through LiveData observer