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?
Related
I'm developing a small application that shows a list, and when an item is clicked it opens a secondary screen with the item details. I want to implement MVP as my architecture for this app, and i have been struggling figuring out how to do that when I have a single activity with 2 fragments.
Some questions came up as when an item from the list is clicked, a callback is sent to the first presenter, but at this point, who is in charge of opening the second fragment? do the presenters 'talk' to each other? should i do it through the activity?
Been looking around for examples of single activity with multiple fragments implementing MVP, but couldn't find something like that yet.
(Yes, it can be done otherwise, but the purpose of the app is to learn implementing MVP on a single activity with multiple fragments)
Appreciate any help!
Thanks!
After looking into different existing MVP sample projects I've decided to follow most of the concepts in the 'TODO-MVP-TABLET' git project by Google which can be found here:
https://github.com/googlesamples/android-architecture/tree/dev-todo-mvp-tablet
I've chosen this solution due to the level of abstraction and the ability to later on reuse any fragment in other activities without changing any code.
Solution principles:
Each fragment has a presenter defined by an interface.
There is a bigger presenter implementing all the smaller presenters.
The bigger presenter holds references to all of the smaller presenters and when a method is invoked it simply delegates the action to the relevant presenter.
Fragments are given the 'big' presenter as their presenter without actually being aware this is the case.
Smaller presenters should hold the reference to the view.
Diagram taken from Google's github page:
Update:
Link isn't valid, seems like Google removed the project from their samples. Will leave it in case they reupload it.
There are possibly many ways to implement MVP. Majorly we use 3 things.
- View
- Presenter
- Modal
you should be clear with your working of screen before creating these things.
eg if you want a login screen.
create structure (using interface) of activity first. like what your presenter and view will contain
eg.
public interface LoginPresenter {
void validateCredentials(String username, String password);
void onDestroy();
}
View structure:
public interface LoginView {
void showProgress();
void hideProgress();
void setUsernameError();
void setPasswordError();
void navigateToHome();
}
Now these are the classes you need to implement on your view class (Activity/fragment) and presenter where your logic part resides.
Now about your queries.
which means the activity will have both presenters instances.
No, your activity should not require to have multiple presenter. it already has opened fragment reference (by findfragmentby id or tag).
who is in charge of opening the second fragment?
you can open it from any of them either Activity/fragment.
if Activity use getfragmentsupportManager
if fragment use getfragmentManager
NOTE: For more info follow this git example.
https://github.com/antoniolg/androidmvp
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.
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!
Firstly, I know that with Model View Presenter there are different implementations, and in my mind as long as you have the layers of abstraction clearly defined and doing their appointed roles then how you implement this pattern is open to interpretation. I have been implementing this pattern in quite a few apps where there was just one Activity. I've now started a new project that has multiple Activities and attached Fragments, including nested fragments (ViewPager).
I'm now trying to translate the MVP to this project and I've hit a concept wall and would like some guidance and insights.
So far I've created the above structure and started to do a 1 : 1 relationship with View & Presenter (regardless of Activity or Fragment). I feel that this is OK, however if for example I sent a request to do something from an Activity View to its Presenter, which returns a result to the Activity View how would I go about propagating the result i.e. update all the other Activities/Fragments that are currently not in a Paused() or Stop() state. I feel like in this case there should be a central Presenter that updates all necessary Activity and Fragment Views, but I'm not sure how to go about doing this.
Currently when each Activity and Fragment is created it creates a new instance of a Presenter class, passing in itself as a reference (the Activities and Fragments implement their own interfaces), which the presenter stores as a WeakReference and can invoke the relevant interface methods when returning a result.
According to the docs whenever Fragments want to communicate with one another and the attached Activity you should use a callback interface. With this in mind should I have one callback interface that the Activity implements and the Fragments callback to whenever they request something, so in essence only the Activity would have a Presenter and Model layer that the Fragments have to callback to in order to make various requests?
Sorry if this sounds a bit muddled, hopefully this is clear enough to understand what I want to achieve, and if I’m thinking along the right lines... or totally off the mark!
I think this is okay to have a presenter inside activity. Basically activity is like a controller, it should know about the presenter.
It would be wrong to put a presenter inside a fragment if activity or other fragment needs it too. You can put a presenter inside a fragment only if this presenter is designed specifically for fragment.
which the presenter stores as a WeakReference and can invoke the relevant interface methods when returning a result
Why do you need a WeakReference here? If you have 1:1 relationship then I assume your presenter does not have it's own lifecycle, meaning that it's lifecycle depends on either activity or fragment. There is no risk of having memory leaks because it's not a singleton, right? It should be safe to have a strong reference.
I'm not sure if I answered your question because it looks a bit broad to me. My point is that, fragments are just separated "parts" of activity and you should treat them as parts. If presenter belongs to this part only, then it should be inside. Otherwise it should be in activity. You are right about using an interface to access activity, this is a well-known design approach which Google uses in their examples.
Nope, no interface anymore. You either use RxJava Observables to update all the views as described here or some kind of Bus(Otto-deprecated or EventBus). And you will like it because they make interacting too easy.
I am creating my app with using fragments. I have something like main activity, it has FrameLayout as root layout to hold fragments.
After much thought I have decided to separate my application logic in several parts, for example : MainActivity is responsible for app basic navigation (MainPageFragment, CategoryListFragment, ProductListFragment, ProductDescriptionFragment), AuthActivity is responsible for autherization, registration (SignInFragment, RegistrationFragment, RecoverPasswordFragment).
A little about my app. If you have recommendation or don't agree with app structure, I would be grateful for any critics.
What is the problem, as you can see my MainActivity has many responsibilities. There are four Fragments now but it can be more in the future.
Lets consider next situation. In my MainActivity I have MainPageFragment and this fragment in turn of course has some views. And on click event I need to change fragment, for instance from MainPageFragment to the CategoryListFragment. In this case I have several ways to handle clicks or other events from framgents.
The most common way is to have activity implements callback interface defined in fragment class as nested class inteface. This approach is quite good and easy to use. But what if my host activity has to handle multiple callbacks from fragments, to say more, there can be more than one callback from single fragment, class(activity) declaration starts growing, class body too. What are another possible approaches to solve this problem.
You can handle all clicks, events directly inside fragment (start activity, replace framgent......) you can do this painless, but for me personally callback approach looks better, but maybe there is nothing bad, and I can use this approach.
Use one or several interfaces for getting information from fragments. For example create class CallbackEvent for holding such info as framgentId, eventType .... Using this approach we can reduce interfaces and methods, but Activity class body can become larger in first approach.
Use something like EventBus pattern to communicate between app components via third party service.
Of course there are some other ways to do this, but I have described most popular.
Please suggest, or just explain how to do you solve this problem in your apps, what approach is better, how to built this communication easy to maintain.
I am grateful for any advice,critics in advance.
If your app becomes more complex using the callback pattern will get messy, especially if fragments need to communicate with fragments. I'd only use that pattern for apps with low complexity (activity, one or two fragments).
Clicks, events etc. should be handled inside a fragment if whatever happens stays within the fragment. Don't replace a fragment from within the fragment, that's the Activity's responsibility. It might look easier to just do a getActivity().someMethod in the fragment but this leads to hard to maintain code. You might understand now what it's doing but will struggle in half a year.
This approach looks messy to me too (similar to 1.)
That's the one I'd recommend. I'm using EventBus (https://github.com/greenrobot/EventBus) but there are alternative implementations like Otto (https://github.com/square/otto) and I've never looked back to the times when I used the callback pattern. Using an EventBus decouples the communication between the different components and your code becomes much simpler and leaner. However you need to be careful with that approach since there are some pitfalls. One is that it gets much easier to communicate from any component to any other component which could lead to even messier code than the listener/observer pattern. Another one is that events are asynchronous compared to synchronous listener calls so you need to make sure you're only receiving the "right" events at the right moment in the component's lifecycle. The main advantages of an EventBus approach are IMO:
A message is always an object forcing the developer to code object oriented compared to the more functional listener method calls
It decouples the different components. Publisher and subscribers don't have to know about each other. Decoupling the components will make your code much leaner and easier to read (and maintain).
It can be used by arbitrary components. E.g. I replaced all LocalBroadcastManager calls by EventBus messages (EventBus is MUCH faster that using a LocalBroadcastManager). Being able to communicate between arbitrary components is especially convenient if the components can't access each other directly (like a Dialog and a Preference object)
I have two rules of Fragment - Activity separation.
One is logic. Anything that deals with View (layout expansion, display, listeners, etc) should go inside a Fragment. Important background processes (http requests, file reading, image processing, etc) should go inside Activity. Part of the reason is explained in my second point:
Lifecycle. Activity's lifecycle outlasts Fragment's. Fragment is also fragile it doesn't even retain its views. And this is the reason Fragment should be decoupled from Activity. Listeners and callbacks are tight coupling and they are the cause of countless null pointer exceptions when some process tries to update a View of a Fragment that has called its onDestroyView. Having said this I'd suggest Publisher - Subscriber pattern like Event Bus where you can plan a message delivery in which it gets digested only when a publisher (which in this case corresponds to Fragment's view) is available.
The numerous click listeners you have are related to how you design your UI. Moving code around doesn't really help much, unless you trim down your layouts.