Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android MVVM: Activity with multiple Fragments - Where to put shared LiveData?

I have an architectural question about the android ViewModels:

Let's say that in my App I have an Activity with two Fragments inside (using a Viewpager). The two fragments do different things (therefore may have their own ViewModel?), but they also both need various data that is similar.

This is for example the state if a network connection is available or not (and both fragments show different error UIs if there is no connection), or some user setting that comes via a Push from a server and affects both fragments equally.

This looks something like this:

enter image description here

Now my question is how to deal with that situation when using ViewModels? Is it good that a view observes multiple ViewModels, like it would be if I have a ViewModel for the Activity (holding the state that both need equally) and one for each fragment, like this:

enter image description here

This was hinted here for example, but it is not a good practice, as the relationship in MVVM generally is

View n - 1 ViewModel n - 1 Model

But I am not sure where the right place for such shared LiveData is in my case?

like image 898
stamanuel Avatar asked Nov 23 '17 16:11

stamanuel


People also ask

Can multiple fragments share a ViewModel?

Multiple fragments in the app will access the shared ViewModel using their activity scope. It is a common use case to share data between fragments in most production apps.

How do I use the same ViewModel for multiple fragments?

It is technically possible to have one ViewModel for all Fragment s. However, since this one ViewModel would have to manage a number of very different use cases, it would be something like a god object. With 20 Fragments, it would have very many lines of code ...

Can we use same ViewModel for different activities?

But you can achieve this by passing a single instance of a custom ViewModel factory which acts as a singleton factory, so it will always pass the same instance of your ViewModel among different activities.


1 Answers

Late answer but I asked myself the same question and found the answer in Google guide. Especially for fragments, it is mentioned on Google Documentations explicitly here

class SharedViewModel : ViewModel() {     val selected = MutableLiveData<Item>()      fun select(item: Item) {         selected.value = item     } }  class MasterFragment : Fragment() {      private lateinit var itemSelector: Selector      // Use the 'by activityViewModels()' Kotlin property delegate     // from the fragment-ktx artifact     private val model: SharedViewModel by activityViewModels()      override fun onViewCreated(view: View, savedInstanceState: Bundle?) {         super.onViewCreated(view, savedInstanceState)         itemSelector.setOnClickListener { item ->             // Update the UI         }     } }  class DetailFragment : Fragment() {      // Use the 'by activityViewModels()' Kotlin property delegate     // from the fragment-ktx artifact     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         })     } } 
like image 54
kiroglue Avatar answered Sep 18 '22 14:09

kiroglue