Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Passing data from one viewmodel to another android MVVM

I have a design-related question for you guys.

So, I have been following Guide to App Architecture by Google to build my application using Kotlin, MVVM and data binding. I am using Jetpack components(navigation, livedata etc) as prescribed by Google.

The issue is that many a time during development I need to transfer data from one fragment to another. Earlier I used to create an instance of the fragment and add the complex data and then move to the fragment, like this:

class Frag1: Fragment(){

    ...
    fun openFrag2(){
        val frg2 = frag2.newInstance(complexDataObj)
        childFragmentManager.addFragment(frg2,TAG)
    }
}

class Frag2: Fragment(){
    var cd: ComplexDataClass = null
    companion object{
    fun newInstance(complexData: ComplexDataClass): Fragment{
        val frag = ActivityFragment()
        frag.cd = complexData
        return frag
    }
    ....
}

With navigation passing data between destination is supposed to be like this or to use Shared View Model which is also mentioned in the same documentation. >>

In general, you should strongly prefer passing only the minimal amount of data between destinations. For example, you should pass a key to retrieve an object rather than passing the object itself, as the total space for all saved states is limited on Android. If you need to pass large amounts of data, consider using a ViewModel as described in Share data between fragments.

This works.

The issue is that one of the main reasons for using an architecture is Separation of concerns; So that we can write clean and maintainable code. This use of sharedviewmodel defeats that purpose(according to my understanding) as this leads to large ViewModel classes.

I will try to explain the problem with a scenario that is quite common.

I have a fragment with a list of data. Each item in the list corresponds to a user. When we tap on an item, it should move to a user details screen, if we tap on the edit button, we should move to the edit screen where the details can be edited.

             View User Frag
             ____                 ____________
            |    |               |            |
 List Frag  |    |               |            |
 ______     |____|               |            |
|______| /
|______|/                        |            |
|______|\                        |            | Huge Shared ViewModel class
|______| \
            Edit User Frag       |            |
            _____
           |     |               |            |
           |     |
           |_____|               |____________|

So in this situation, the ViewModel will be shared between these 3 fragments as the User data needs to be sent from the list class to the view and edit fragments, and the shared ViewModel will have the business logic of all three fragments.

So this does not seem to be right to me, because the ViewModel will be too complex to manage in many cases as sharing like this:

model = activity?.run {
        ViewModelProviders.of(this)[SharedViewModel::class.java]
    } ?: throw Exception("Invalid Activity")

will give the same instance of the viewmodel.

I need to know if my understanding of this sharedviewmodel is wrong, if so please correct me. If my understanding is right, please let me know how to manage the view model more efficiently in such cases.

like image 793
hushed_voice Avatar asked Oct 26 '19 17:10

hushed_voice


1 Answers

You can have multiple ViewModels in a Fragment, so there's no need to keep a huge shared ViewModel with all the logic of the 3 smaller ones.

You can create an extra shared ViewModel that only cares about the actual common data, and keep your 3 separate fragment specific ViewModels separate.

sharedModel = activity?.run {
        ViewModelProviders.of(this)[SharedViewModel::class.java]
    } ?: throw Exception("Invalid Activity")
localViewModel = ViewModelProviders.of(this).get(LocalViewModel::class.java)
like image 109
Mircea Nistor Avatar answered Oct 23 '22 08:10

Mircea Nistor