I am converting my application to use the MVP pattern. There is some debate between the developers on the proper use of MVP especially in regards to the Android lifecycle and where the UI related logic goes. There is no debate that any hard logic should be done in the presenter, and that the network
In the case I need to do Anything for lifecycle functions, onresume, onPause, etc. Should I ...
Call a mPresenter.onResumeEvent(); The presenter then does calls. IE
contract.restoreState(); contract.connectToService() etc.
or
Do all the logic I need here and not involve the controller. IE
restoreState, start up loading spinners, etc.
I view it as onResume is an event. All events should be processed by the Presenter. The counter arguments is, we do not want to write code that "ping pongs," I.E. OnResume -> Presenter -> one line function that shows a spinner (or something close to that effect)
Now a bit more granule.
Lets says I start my activity, and I need to show either an error or the data depending if the data is null.
I could either do..
(presenter)
contract.setupUi(data);
then
(view)
setupUi(Object data){
if(data != null){
//show data
}
else{
//show error
}
Which has the UI controlling the state evoked from the presenter.
Or I could do
(presenter)
if(data != null){
contract.showUI(data);
}
else{
contract.showError();
}
Which has the contract looking at all the states.
Is the over all goal to have the Presenter Completely control everything about the application and treat the view as completely Dumb. Or is it just dividing up the code purely for testing purposes. Or is it both?
Recap.
How should I handle the lifecycle -- treat it as an event or let the
view just do it.
Where should the view related logic go? Let the Presenter figure out
what is null and what UI to show. Or let the view take care of it?
What should my over all focus be? Controlling the app with the
presenter, unit testing, both?
Very good questions, but, unfortunately, they do not have definitive answers.
It boils down to the fact that MVP (or any other MVx) is not a specific implementation, but rather a high level architectural pattern which is subject to interpretation.
Said that, my answers to your questions:
I'm a strong believer that UI logic doesn't belong into Activity/Fragment at all, therefore MVx views should never be aware of lifecycle events.
UI logic goes into standalone class that takes on responsibility of MVx view. Where you put null checks depend on the purpose of this check: if the result only affects UI (e.g. show/hide UI element) then perform the check in MVx view; if the result affects application's flow (e.g. show prompt dialog, change screen, etc.) then perform the check in the presenter; if both - perform checks in both presenter and view
Your overall focus should be on writing a maintainable code. Maintainable, first and foremost, means readable.
Again - the above answers are IMHO.
You might also be interested in this series of posts that I wrote: MVP and MVC Architectures in Android
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 like MVP concept, it helps me a lot to organize a code, but every time when i need to get a result from external app, from dialog, or request permission, I confront the same question - which component of architecture should care about this?
For example, we need to implement following behaviour:
click on the button starts Google voice recognition intent
if we have more than one result - show a list dialog and let user to
choose right variant
do smth with it
So, we can do smth like this (also decide that Fragment implements View, contains link to Presenter and sends UI event to it):
interface View {
void showRecognizer();//2
void showChooseDialog(List<String> items);//4
}
interface Presenter {
void onButtonClick();//1
void onRecognizerResult(List<String> results);//3
void onResultChosen(String result);//5
}
Ok, it will work, but we have some problems:
Algorithm is not fully encapsulated - if you want to change it, you would have to change view and presenter interfaces
If you have a few algorithms like this on one screen, your V & P interfaces will be huge and difficult to read and understand
View becames a little bit clever than it should be (both V & P knows about 1, 2, 3, 4, 5 sequence), Presenter knows about details (dialog is an implementation detail, but it asks View to launch it)
Algorithm is not reusable! How to use it on other screen?
So, I want to know your opinion about this, how it can be done better (or maybe you think this is ok)?
And generally speaking: starting dialogs and activities, requesting permissions, handling results, whose duty it is from the point of MVP and clean architecture?
Any thoughts or suggestions are encouraged. Please help me to clarify this, thanks.
My 5 cents about MVP:
Some things are just not avoidable in View part, like starting and listening to some services (example: google maps or places).
When doing something like that, I try to leave as little logic in View and notify Presenter of any interaction (even if not useful at that moment) and then returning the action that is needed to View.
My listeners usually trigger presenter and nothing else. Then presenter triggers the view to do some function. This may be an overkill but I don't want my presenters to feel left out.
In your case, View would start a dialog and/or permission request but presenter would order it to do so. Then when the results come back, give them to Presenter to decide what to do with it (as long as you don't pass Android stuff like views).
Hope this helps.
For example if there's an activity with a button(View). When this is pressed, it calls a Presenter method, this method gets an observable from a service(Model) - which could take a long time to reply with results.
Should the subscriber for these results be kept on the Presenter? Then depending on the results, the Presenter would call the relevant View's actions?
Or should the subscriber be on the View? As I've been seeing in these other rx android example projects. In which case the activity/fragment would be calling other View or Presenter methods depending on the subscription's results.
The main goal of MVP pattern is to decouple the data access mechanism from view(activities, fragments). To make an application to be easily extensible and maintainable we need to define well separated layers.
If you return you subscriber on the view then it will break the MVP pattern. You should make your view as dumb as possible. So you should subscribe on presenter layer and let the presenter layer decide what should be the next step in the view. There might be some situation arise when different kinds of action might happen on the view. That logic should not be present on view.
**NB:This is just a suggestion. Make your view dumb. But you have to decide how much dumb you will make the view based on the action it performs. For an example there is a button whose click event pop up a yes/no kind of dialog. You should not call the presenter that the button clicked and let it tell the view to open a dialog.
But the situation you describe above you should use a presenter layer.
Presenter should do all the logic and heavy lifting while view is simple as possible. It only registers user input and, after all is done, shows the results.
Should the subscriber for these results be kept on the Presenter? Then
depending on the results, the Presenter would call the relevant View's
actions?
Yes, this is correct way to do it.
I would suggest to always keep subscription on Presenter. If View is allowed to 'see' the Model, it should only interact with Model in some simple manner such as data binding and simple validation. Otherwise, View is dump, Presenter proceeds all business logic.
Passive View and Supervising Controller are two variants of MVP for your references.
Please also checkout a new MVP framework for Android at http://robo-creative.github.io/mvp. Samples on there explains the difference between those variants. Have fun!
I want as my application to be structured in 2 parts: the logic code and the UI.
I've tried to implement that using a controller class(here I keep the logic code) inside of each activity.
The activity send messages to controller and receive the answer in two ways:
the answer is returned immediately (if the action is not complex and it can be done in a verry short time)
the activity set some listeners and the controller fire this listener when the action is complete.
The problems appears when the controller have a lot of objects(each object should handle a set of actions and for each action I have to set & trigger a listener): it is hard to keep the code syncronized.
I'm asking if you know a better way to implement this mechanism.
Thank you.
Personally, I consider the Activity to be the controller. Widgets are the view. Others may disagree, and I am far from an MVC purist.
Android methodology is pretty MVC.
Start by getting good at Views, then look at extending things as you see fit.
The views connect to the controller via the UI thread, which is the main thread of the application. You can define callbacks and such in the XML and handle all button clicks and such in this thread by just using the android xml methodology.
You should consider XML to be the View, UI Thread the Controller, and Background Threads/Services/Broadcast Receivers etc to all be part of the model.
You can follow "Model View Presenter(MVP)" pattern which pretty much organises the code and keep the code segments clear.
I like the dummy view approach where all views events (like onClick, onLongClick.. ) are delegated to presenter and presenter takes care of the business logic and updates the View back.
Consider a scenario where user is adding some text to his note and In view, we have a textbox, texfield to indicate the status and add button.
User types text and clicks add button.
AddButton: "Hey Presenter! User wants to add something".
Presenter: "Give me your text, TextBox".
TextBox: gives the text typed.
Presenter: Validates the text with buisness logic.
adds item to database using Model classes and sends the status text to StatusTextView to show.
StatusTextView: updates its text which is sent by the presenter.
As you can see, Views do what Presenter says. You can have different flavours of Presenters to act differently to user interactions.
Some points to consider:
Keep presenter out of android classes so that you can unit test it
separately later.
Connect view and presenter with interfaces (contracts) so that you
can plug different views and presenters later with changing app
requirements
Use Dependency Injection frameworks like Dagger2 to even more
decouple the hard dependencies.
Google about MVP and choose your preferred way of implementation. Only con I felt in MVP is your code will become huge yet clear.
Few links:
https://medium.com/cr8resume/make-you-hand-dirty-with-mvp-model-view-presenter-eab5b5c16e42
https://www.journaldev.com/14886/android-mvp
Happy coding :)