Search code examples
androidandroid-fragmentsandroid-viewpagerandroid-livedata

LiveData is not observing on child viewpager fragments having a shared viewmodel


LiveData is not observing on child viewpager fragments where the child fragments have one shared viewmodel to access data.

Here FragmentA and FragmentB are part of a viewpager and both of them are sharing one viemodel SharedViewModel.

public class SharedViewModel extends AndroidViewModel { //in Java

    private final MutableLiveData<Data> mLiveData = new MutableLiveData<>();
    public LiveData<Data> getLiveData() {
        return mLiveData;
    }

    //for updating data through LiveData, using post as and when I get the response from DataSource as shown below.

    mLiveData.postValue(response); //getting the response on debugging
}
class FragmentA : Fragment()  { //in Kotlin

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

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View {
        ....

        mViewModel.liveData.observe(viewLifecycleOwner, {
            //no call coming in this block so unable to update view
        })
    }
}
class FragmentB : Fragment()  { //in Kotlin

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

Need some help as to why the live data is not able to observe the changes.

Thanks in advance.


Solution

  • Your ViewModel is not shared. you have named it as sharedViewmodel but the way you are getting an instance of it by passing a Unique Owner it will also be a unique instance.

    the correct way of sharing view model is

    class SharedViewModel : ViewModel() {
        private val myLiveData = MutableLiveData<Data>()
    
        fun getMyLiveDta():LiveData {
          return myLiveData
        }
    }
    

    Now in the first fragment

    class MasterFragment : Fragment() {
    
        private lateinit var itemSelector: Selector
    
        // Get instance of viewmodel in fragment like this
        private val model: SharedViewModel by activityViewModels()
    
        override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
            super.onViewCreated(view, savedInstanceState)
            
        }
    }
    

    And in the second fragment like this

    class DetailFragment : Fragment() {
    
        private val model: SharedViewModel by activityViewModels()
    
        override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
            super.onViewCreated(view, savedInstanceState)
            model.selected.observe(viewLifecycleOwner, Observer<Item> { item ->
                // Update the UI
            })
        }
    }