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.
You can have multiple ViewModel
s 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 ViewModel
s separate.
sharedModel = activity?.run {
ViewModelProviders.of(this)[SharedViewModel::class.java]
} ?: throw Exception("Invalid Activity")
localViewModel = ViewModelProviders.of(this).get(LocalViewModel::class.java)