Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ViewModel for Fragment instead accessing Activity ViewModel?

Tags:

The problem is quite straightforward. The question is in context of using ViewModels, LiveData and other related Lifecycle aware arch approaches.
I have an Activity with NavDrawer, which switches fragments inside.
And also I have a case when two fragments are present at the same time on the screen - this will be the main pain. One Fragment has a ViewPager with nested Fragments(don't ask why). The other fragment is just obtaining info from first one when user performs some actions. This is achieved just by sharing activity viewmodel. But the app itself has a lot of business logic and as it goes further the viewmodel goes bigger and bigger.
What I want to ask - not a receipt or rules how to fix this, or maybe how to overcome this by fixing the entire structure of the project. I want to ask for suggestions how can I apply the MVVM approach within android.arch.lifecycle style to mine use-case.
I haven't seen something more complicated then just sharing the Activity ViewModel between Fragments. But common, that's not a cure. enter image description here

What you can see here - a mess actually. The point is that all are sharing the ActivityViewModel. Connections(aggregation) from FirstFragment mean that ViewPager inside FirstFragment is initiating ChildFragments and they are also working with the same ActivityViewModel(kill me). So as result everyone is working with one shared ViewModel.
My proposal is to add a ViewModel for each Layer. So that Activity/Fragments/ChildFragments have their own ViewModels. But what appears here - how we should communicate then?
Possible solutions :

  • Having two ViewModels per one component. One ViewModel will handle/delegate the business logic and another will make the communication. Two viewmodels per component - not so good, yeah?
  • Having old manner interface(please no!)
  • Other workarounds - like DB/SharedPrefs/Realm change listeners and Event Buses(I'm too old for this :( ).

  • Your solution here!

I'll say that all of the above are breaking a lot of design principles, so what should I do? How should I come out of this mess? Is there any Uncle Bob or another superhero here to help?

P.S. - Well, creating UMLs or other charts isn't mine forte. Sorry for that.
P.P.S. - I'm aware of google samples.

like image 510
Yurii Tsap Avatar asked Sep 17 '17 20:09

Yurii Tsap


People also ask

Can a fragment have a ViewModel?

In android, we can use ViewModel to share data between various fragments or activities by sharing the same ViewModel among all the fragments and they can access everything defined in the ViewModel. This is one way to have communication between fragments or activities.

Can a fragment have multiple ViewModel?

It is technically possible to have one ViewModel for all Fragment s.

How do I view ViewModel in fragment?

Use activity's scope to create an instance of the ViewModel in fragment so that all the fragments and activity now has a common ViewModel and have access to the same ViewModelStore . If the activity is re-created, it and all its fragments receive the same ViewModel instance that was created by the associated activity.


Video Answer


1 Answers

What i would suggest you can do is handle two ViewModel for your entire use case.

Make one ViewModel

Let's say MyActivityViewModel to handle all logic related for activity level. So, if any fragment logic is directly related to your activity then share your ViewModel like below :

ViewModelProviders.of(getActivity()).get(MyActivityViewModel.class); // Like this in fragment. 

&

ViewModelProviders.of(this).get(MyActivityViewModel.class); // Like this in activity. 

This will share common ViewModel between your activity and fragment.


Another ViewModel would go for FirstFragment in your case if you have to share logic between your ChildFragment :

Here you can share ViewModel let's say FragmentViewModel like below:

ViewModelProviders.of(this).get(FragmentViewModel.class); // Like this in FirstFragment which is having view pager. 

&

ViewModelProviders.of(getParentFragment()).get(FragmentViewModel.class); // Like this in View pager fragments, getParentFragment() is First fragment in our case. 

Although, we can still use our activity level MyActivityViewModel in our child fragments from FirstFragment like :

ViewModelProviders.of(getActivity()).get(MyActivityViewModel.class); 
like image 117
Jeel Vankhede Avatar answered Oct 19 '22 08:10

Jeel Vankhede