Hello devs I have one questions I hope you can help me.
I have read that Google recommends having a View Model for each screen, a screen could communicate with the View Model to perform many different actions. So the View Model would have many responsibilities, which is against the S of solid. Would it be good to have the necessary View Models for each screen so that each one has a single responsibility?
This multiple View Model approach I believe would improve reusability, encapsulation, and fragmentation; since if two screens need to do the same action, there is no need to duplicate the code of the corresponding View Models or pass the same use case to both. Each screen would access what you need.
You have asked a great question.
These are just my opinion:
You mentioned multiple ViewModels for one screen(let's say 'view') and the Single Responsibility Principle.
1: Yes you can use multiple ViewModels for a view. But it is not typical in MVVM structure.
2: The main purpose of ViewModel is to separate your concern and can test the logic of the app without launching the device or emulator(run at JVM level)
3: SRP is not just the way you consider in ViewModels, Let me give you an example: Imagine you want to validate an email or phone, ... in your ViewModel, You can make a class for validation that follows SRP(It has single responsibility), Now you can use this class where you need it in ViewModels. define your shared classes, repositories, or use cases that follow SRP and use them in your ViewModel, Not define multiple viewModels in your views, I believe that each view has its own viewModel.
In android, viewModel also was designed to hold data for views. It means when your configuration changes your activity and fragment's data will not destroy.
Hope this helps you :)
Related
I am working on a small application using MVP pattern. My home activity has viewpager with multiple fragments in it and each fragment has its own presenter. Fragments aren't communicating with each other so the activity doesn't have any logic, it is just initializing fragments on start.
So if I would like to implement the pattern by the book and stay true to its principals should I implement presenter also for the activity? And if so what should be its role?
If you want to implement MVP by the book and stay true to its principals, every UI that has user interaction should have a presenter. In this case, if your activity is not interacting with the user, there is no need to have a presenter, and your fragments can have their own. If your activity needs, let's say show a loading to the user because of some data loading prior to show the fragments (this is a user interaction because you are interacting with the user to let them know that something is happening so they should wait), then might be good to consider having a presenter for the activity.
MVP doesn't care at all about whether is an Activity/Fragment/View, it just knows View which is considered as an abstraction of whatever can be shown to the user :)
That is at least, from the 'rules' perspective. My 2 cents is, be flexible, if you see that it actually ends up adding value to you and your project, do it, otherwise, sometimes you have to 'break' the rules or create your own.
For using the fragments with their own presenters, I try to use the presenter-contract classes duo to manage the UI events in the fragments.
For example, Consider a click event to show a toast message in case of two possible outcomes: 1. Save and 2. Delete
Then, I will declare two view contract methods like this:
interface View{
fun showSaveMessage()
fun showDeleteMessage()
}
And then, in the fragment, I will use an instance of my presenter class to display the messages at appropriate times like: presenter.doSaveAction(), the presenter in turn will cause the view to show the toast message.
Also, when I come to the actual logic of the fragment, like for fetching some data from a remote server, I use Interactor class along with the Presenter-View classes to perform it.
I believe staying true to all the principles is virtually dependent on what kind of application you are building. Sometimes, it is more feasible to use MVVM with MVP than only MVP pattern for the app architecture too.
I hope this answers your question, kind of?
Is there a difference between the "newer" Model-View-Intent architecture compared to the "older" ones like MVC and MVVM?
What issue does MVI address? What are the similarities with MVC/MVVM? What are the differences?
There are similar questions already on stackoverflow for MVC/MVV/MVP but none so far that explains MVI.
What is the difference between MVC and MVVM?
What are MVP and MVC and what is the difference?
from my experience each architecture pattern of those was invented to solve specific problem that the previous one ignored or wasn't observed yet.
MVC - Model View Controller
in UI applications the responsibilty of rendering the data to the screen, or the business logic and bind those together at first wasn't clear. so MVC came to define those responsibility to three components, each one has one purpose, and the picture describe the relation between those three components.
View - is the UI component that has all the properties like color, shape, tools to listen to the click events .. etc.
Model - is the component that define the business logic that you want the view to render and behave accordingly.
Controller - is the one who change the model, so if the view has a name for example to save, View pass it to the controller then controller manipulate the model with the right actions.
MVP - Model view presenter
the problem with MVC that there is a great coupling between the three components, if you want to change the view calls, it will require you to update controller and the Model.
and that's clear from the MVC picture, the relationship between the three components is very tied, you couldn't replace one of those components without the other.
So MVP came to provide a more clean solution to the previous problem by separating the Model and the View, keep the interactions between them via the Presenter, Presenter is the middle man that each the view and the model call.
So if you want to save a list of favorites movies, View listen to user (*) action, then call the presenter function that update the model, then model tells the Presenter if that succeed or not, and Presenter tells the View to show the right message.
MVVM - Model View ViewModel
with the rise of reactive paradigm, it was clear that we can provide more separate of concerns in UI Applications by just observing the changes and behave on it.
so for example there is a click in view that need to call an api to get latest tv shows.
this view click will be observed at the ViewModel, ViewModel interact with the model to get the data, and finally ViewModel post those data on the view using other observer ..
so in short, View observe ViewModel to get UI updates, and ViewModel observe View to call the right action with the Model. Observer pattern has proved his worthy in decoupling logic so here you go a new Pattern.
So after talking about the most popular architecture patterns, each one has tried to decouple the UI code from the business code. but the previous patterns doesn't bound updating UI with different states in the same time.
if you had an issue that related to the loading appear with an error message showed at the same time, you will understand what I'm talking about, so to maintain UI state, you have to do extra effort looking what you wrote wrong causing those kind of issues.
MVI - Model View Intent
MVI is based on an old idea called finite state machine, any system or component has predictable, set of states is a finite state machine.
in MVI any update to the UI is defined by new state, you could find this is overwhelming, but imagine that you have a screenshot for each time UI changes, that's the state. you can debug, test, reproduce the state issues now.
how to achieve this, that's the MVI in practice.
any user interaction with the UI, is defined in MVI by an Intent, Intent is what the user need from this action, it could be star a movie, refresh the screen, it even could be opening the screen, in that case the Intent is an initial intent to show the screen with all required data.
which component get those Intents to act according on them, that what you define .. you could use a Presenter or a ViewModel, it doesn't matter, MVI is more a practices than using a new middle component.
I'll continue with ViewModel, ViewModel will get those intents, decide which usecase to call (Model behaviors).
all usecases pass by summer function in the ViewModel, that decide which state that needs to be reflected to the View, it provides you with previous state too, so you have the previous and the new state to update the screen, which reduce the rendering updates, and View get only the new hints to update itself.
and finally MVI is uni directional flow, it starts with the View and ends with the View.
... View -> ViewModel/Presenter -> Model -> View -> ...
MVI is different in the way of managing the state, it's a combination of several ideas to build more stable, and testable app.
A really great breakdown is here: https://academy.realm.io/posts/mvc-vs-mvp-vs-mvvm-vs-mvi-mobilization-moskala/. At it's core, MVI is taking the ideas of MVVM (stateless UI state), separate business logic and models, and putting the reactive framework on top of it. Making things streams of events instead of discrete actions, making receiving elements consumers of transformed streams instead of presentation elements, and making state a read-only, disposable thing that is acted upon explicitly in a very structured way.
This requires that you take a functional approach to writing your application, especially the UI/View part of things. State is not modified, new state is calculated from an intent and a series of use-cases. This is fairly well explained here: https://proandroiddev.com/mvi-a-new-member-of-the-mv-band-6f7f0d23bc8a.
It is intended to address the growing complexity of modern UI applications, who have a non-trivial amount of client-side state that needs to be managed explicitly. As most experienced programmers know, the most complex failures come from state that is being modified in an unexpected way. This state manipulation can result in "invalid" states that your application cannot handle, which is effectively a crashed application. MVI addresses this by making state transitions explicit and carefully structured so that they system never comes to an invalid state, and the state is always understandable.
I work on rewriting my app to MVVM architecture concept.
Based one my understanding all the business logic should live in the ViewModel and the UI components in the Activity or Fragment. I use a third party library that needs to be initialized with some view's like: MyLibrary instance = new MyLibrary ("key" , imageView, surfaceView) and then doing some manipulations on these views.
What would be the best place and the right way doing that knowing that it's not recommended passing any Android view to the ViewModel and also not the right thing to initialize SDK in the Activity
You have already answered your question. It's the other way around, the ViewModel informs the View (activities and fragment) WHAT should be chaged, and the View simply handles HOW it should be updated.
Most of the business logic however, if we want to be nitpcky, should still remain in the model. The ViewModel only holds the LiveData that the View needs. Some reasons for this is that you don't want your model to be Android architecture dependent. But also to follow the single purpose principle. This way you avoid making the ViewModel into a God object that handles everything. Instead you only allow it to format data, pass commands, provide factory methods for binding
to the viewModel, and subscribing/getting relevant changes from the model.
So in short: The View passes user-input to the ViewModel who issues commands on the Model. The ViewModel then format the changes from the Model and posts the changes using LiveData to the View. The View finally updates the components that the user can see.
Check the example here for how the UI is updated.
https://developer.android.com/topic/libraries/architecture/viewmodel
Read more about the pattern here:
https://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93viewmodel
While building Android App using MVP pattern, I am wondering should I use presenter activity-wise or functionality-wise?
Activity-wise means, number of presenters equivalent to number of Activities.
Functionality-wise means, for each functionality, should use separate Presenter.
Functionality-wise, so you can reuse presenters in multiple activities.
Also: A Presenter should not have references for Views or even Context for testing purposes.
My personal approach is that it depends on the logic, each has it's pros and cons.
Let's say an activity has a list fragment and a details fragment, if theses fragments you are pretty sure they will only be used with this activity then you can have one presenter, but what if you want to use the detail or the list fragments in other activities, or if it's a list of people and the detail for each person, then you can open the logged in user detail view ( from a place other than the people list) ? you will use the same presenter of the activity ( not that good architectural wise ) so in this case having 2 presenter in my own opinion is a better approach!
To cut it short, there's no rule for it, it just depends whether if you are going to use the views in other scenarios or the view is only attached to this Activity.
To me it should be Activity-wise as a screen may have more functionalities and having presenter for each one of them will require way too many presenter and also organising them into one screen will be a pain.
Between it is a opinion based question.
On MVVM pattern, the ViewModel contains business logic and notifies the View when it needs to be updated. It is also notified by the view about user events.
As I understood it, each Model should have an associated ViewModel. So, if we have the following models:
User
Account
We would have the following ViewModels:
UserViewModel
AccountViewModel
However, all examples I find about data binding with MVVM, use a single ViewModel for a layout. And recently, Google has introduced the ViewModel class within Architecture Components. This leads me to believe an Activity would have a single ViewModel that would connect to all related Models:
User / Account --> ActivityViewModel
This gets even more complicated if we think of a RecyclerView. Each adapter item could be a ViewModel itself, so an Activity with a RecyclerView would have multiple ViewModels within the list and plus a master one for the remaining view contents (assuming they require information from a ViewModel). For instance:
In this example, we have a list of Account ViewModels and one UserViewModel. How would this be embedded into a single ActivityViewModel?
You should have one ViewModel per View (Activity, Fragment or Custom View), with multiple LiveData, one for each logical unit. In the image one logical unit would be the user data, another logical unit would be the settings data, so you would have two LiveData exposed in the ViewModel.
These concepts can also be visible in the recommended app architecture google presented in the last Google I/O, where an Activity/Fragment has 1 ViewModel with multiple LiveData:
Google suggests that you use 1 ViewModel per View (i.e., Activity or Fragment) (see https://youtu.be/Ts-uxYiBEQ8?t=8m40s), and then inside each ViewModel you can have more than 1 type of Model. However, the MVVM principle is to have only 1 Model type per ViewModel, so Google's presentation contradicts that :/. I guess you'll have to decide what approach works better for your app.
About the list example you mentioned, that is not how you'd do it, for lists you'd use the paging library. You can see details on how to use this at the end of the video I linked above.
One view model is standard. However, even google suggests that you may have more than one view model. That comes quite convenient when you mitgrate a phone app towards a tablet app. When you combind more than one phone views on a single tab view, then it is convenient re-using the models.
If you have the SOLID principles in mind when coding, then the S (single responsibitly of a class) may cause you to use more than one view model.
However, one per view is pretty much standard and you shold have reasons, as metioned above, to use more than one.
What is the relationship between Users and Accounts? If these are two separate, unrelated models, then they should each have their own views and view models. Remember the single responsibility principle: each module should be responsible for only a single part of your logic. That way, any changes to your domain logic or models will only affect that part, and that part only.
In general it is okay to have 1 View with multiple ViewModels.
View - answers the "how", how should a UI rendered. But it should never answers the "when".
ViewModel - answers the "when", it's the presentation logic and tells when should the view be rendered. ViewModel should never have reference to any View. Instead View observes and listen on ViewModels.
Model - answers the "where", it's the business logic which handles data (local/remote) request. Where to read data and where to write.
As long as ViewModel do not have any reference of View, it should be okay since we can have a situation with Fragment that has its own ViewModel and another ViewModel which comes from its host Activity. We also have a so called shared ViewModel which uses by activityViewModels() that can be use by the Fragments inside the Activity.
You will have a Fragment that has 1 ViewModel own by the fragment itself and 1 ViewModel own by the host Activity.