Use multiple presenters for the same Activity - android

I'm trying to use MVP in my new project. I have a Single Activity and multiple presenters that can be associated with it.
Presenter1 - Load Activity Data
Presenter2 - Load User data - that can be used in multiple Activities (So this presenter will be used in multiple activities
Presenter3 - User Actions - This can also be used in more than one Activities.
For now, I have used all the 3 presenters for one Activity. Is there anything I can do to use only single presenter to access all the methods for the 3 presenters? Searched a lot, but could not find any relevant reference. Thanks

I'm not sure it is the answer you're looking for but you could try an architecture more like clean architecture and isolate the logic of each of your use cases in an interactor and then inject your three interactors in one unic presenter for your activity.
And later, when you'll need to re-use that logic you will have a LoadUserInteractor and a UserActionInteractor to inject into that new presenter.
If you do not want to create interactors in your architecture you could create an abstract present who have the methods for load user data and user actions and let your activity presenter extends it with the load activity data but I'm not sure it will be long before it cause you some maintenance problems.

Related

Does every view have to have presenter in MVP pattern?

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?

Should we Use ViewModels to communicate between 2 different fragments or bundles in single activity App Architecture?

Scenario 1 - If we use ViewModels to communicate between fragments, then the ViewModel has to be created by activity reference and hence going to stay there in memory until the activity is destroyed.
Scenario 2 - In master-detail flow ViewModel makes our life easier but again the memory usage issue is there.
Scenario 3 - We have viewModelScope in the new version of arch library to cancel jobs with Fragment/Activity lifecycles, but if ViewModel is created with activity reference then it's going to stay there until activity is destroyed. Hence the job can still be executing and fragment is already gone.
You can use ViewModels to communication between two different fragments(aka SharedViewmodels) because it's simple but it's not perfect.
As you know the SharedViewModels must be alive until the first joint parent (activity or fragment) is alive.
but wait ...
What is the purpose of ViewModels?
Are we create ViewModels just for communication between fragments? Absolutely not.
Is the use of ViewModels against the purpose of ViewModels? no, I say it's not perfect use them for communication between fragments but if you have a small project you can use them because it's simple.
So what can I do instead of using ViewModels for communication between fragments? You can build independent UI components and use them for communication between fragments.
What is the advantage of building this weird independent UI components? In this way, each component has its own ViewModel (or Presenter) and they haven't any parent/child relation; Instead, they updated from the same business logic or in reactive programming they are just observing the same Model.
What is the meaning of building independent UI components and how to build them? if you are already familiar with reactive programming, I recommend reading this amazing blog post by Hannes Dorfmann; If you don't, I simply propose using EventBus library for communication between fragments but You will soon realize that too much usage of this library leads to spaghetti code.
Scenarios
If the fragments are not part of a flow/group, then don't share the ViewModel, just pass some id/data to the new fragment, create its own viewmodel, and query the data for the fragment from its own viewmodel.
If the fragments are part of some flow/group (cart/checkout/booking flow, multi-screen registration process, viewpager fragments, etc) and the logic is common enough, then share the viewmodels between the fragments. In single-activity architecture, I put these flow/process in its own root parent fragment that acts as a host and is used to create the scope of the viewmodel. For example:
MainActivity ->
-> RootAuthFragment
-> SplashFragment (replace with below)
-> LoginFragment (add to backstack with below or onsuccess login go to MainFragment)
-> SignupFragment (onsuccess go to Main)
-> MainFragment (replace with RootAuthFragment)
In the above scenario, you can share the viewmodel between login and signup screens with RootAuthFragment's scope. If you have a multi-screen signup process, then you could move that into separate root fragment and create a separate viewmodel for the signup flow.
Bundle vs ViewModels:
Bundles are used to pass some values. So, use it just for that. I use bundles to usually pass primitive data types or enums and based on that I query the actual data from the viewmodel (through android room or retrofit) or if the data objects are small enough, I make them parcelable and just pass that.
If you have a shared ViewModel and it's becoming a god class and does a lot of different things, then it means those fragments need separate ViewModels. Don't share the ViewModel just for data. Share the ViewModel for the common/shared behaviour/data/logic (whichever makes sense for your particular use cases)
I prefer you should use View Models approach if you are using single activity architecture. To justify my answer I will clear your scenarios here.
Scenario 1 - If we use ViewModels to communicate between fragments, then the ViewModel has to be created by activity reference and hence going to stay there in memory until the activity is destroyed.
Scenario 2 - In master-detail flow ViewModel makes our life easier but again the memory usage issue is there.
As for memory you are already holding information into memory there is no escaping there. If you don't need data for stay there then you can clear data from models also but again it will kill the purpose of storing data in the first place.
If you pass data using bundle it's also going to take memory there also.
Scenario 3 - We have viewModelScope in the new version of arch library to cancel jobs with Fragment/Activity lifecycles, but if ViewModel is created with activity reference then it's going to stay there until activity is destroyed. Hence the job can still be executing and fragment is already gone.
That's the main purpose of using view models it will store the last state for user where he left.
As per https://developer.android.com/topic/libraries/architecture/viewmodel states
This approach offers the following benefits:
The activity does not need to do anything, or know anything about this communication.
Fragments don't need to know about each other besides the SharedViewModel contract. If one of the fragments disappears, the other one keeps working as usual.
Each fragment has its own lifecycle, and is not affected by the lifecycle of the other one. If one fragment replaces the other one, the UI continues to work without any problems.

In MVP pattern, should Presenter be activity-wise or functionality-wise of Android app

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.

Multiple Activities / Fragments and the Model View Presenter pattern

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.

Android pattern to make code inside activities more readable

I read about MVP patterns. When we are starting developing android applications we are almost by default using MVC (we usually have our models in "models" package, views are inside "res" folder and activities are basically controllers.
I have realized that some activities inside my applications are not very readable, they are easy to understand but it take some read it because of the amount of code (for example,set up listeners for seekBars, handling sending data do AlertDialogs,receiving data from AlertDialog, validation of data before sending to server.
I don't see any benefit of starting using presenter (in MVP pattern). Presenter holds reference to activity, and when I want to do something with my view(change some EditText for example), I will call some method on presenter that points back to some method in my view(activity).(Explained here) All interactions with views are still handled inside activities which makes it hard to read.
Currently I implemented presenter layer just like some facade layer above activity. For example, there are methods like BindModelToUiViews() that have lot of code for setting up initial views(controls) on screen. What is best practise to make android activities "clean" and more readable(maintanable)?

Categories

Resources