Skip to content

Instantly share code, notes, and snippets.

@vxhviet
Last active November 17, 2021 01:35
Show Gist options
  • Save vxhviet/2479c2343ea2a93dd35ee66d0416e9b5 to your computer and use it in GitHub Desktop.
Save vxhviet/2479c2343ea2a93dd35ee66d0416e9b5 to your computer and use it in GitHub Desktop.
Android MVP General Guideline and Best Practices

Source: Francesco Cervone, Florina Muntenescu, Android Architecture Blueprint

Android MVP General Guidelines

--------        -------------       ---------
| View | <----> | Presenter | ----> | Model |
--------        -------------       ---------

The main differences between MVP and MVC is MVP breaks the connection between View and Model land let Presenter effectively become the middle-man to do all the talking.

- Model: it is an interface responsible for managing data. Model’s responsibilities include using APIs, caching data, managing databases and so on. The model can also be an interface that communicates with other modules in charge of these responsibilities. For example, if you are using the Repository pattern the model could be a Repository. If you are using the Clean architecture, instead, the Model could be an Interactor. The Android Architecture Blueprint uses Repository (see the Repository Pattern Gist for the implicit difference of Repository pattern used in Android project).

- Presenter: the presenter is the middle-man between model and view. All your presentation logic belongs to it. The presenter is responsible for querying the model and updating the view, reacting to user interactions updating the model.

- View: it is only responsible for presenting data in a way decided by the presenter. The view can be implemented by Activities, Fragments, any Android widget or anything that can do operations like showing a ProgressBar, updating a TextView, populating a RecyclerView and so on.

Android MVP Best Practices:

1. Make View dumb and passive:

One of the biggest problems of Android is that views (Activities, Fragments,…) aren’t easy to test because of the framework complexity. To solve this problem, you should implement the Passive View pattern. The implementation of this pattern reduces the behavior of the view to the absolute minimum by using a controller, in our case, the presenter. This choice dramatically improves testability.

For example, if you have a username/password form and a “submit” button, you don’t write the validation logic inside the view but inside the presenter. Your view should just collect the username and password and send them to the presenter.

2. Make presenter framework-independent:

In order to make the previous principle really effective (improving testability), make sure that presenter doesn’t depend on Android classes. Write the presenter using just Java dependencies for two reasons: firstly you are abstracting presenter from implementation details (Android framework) and consequently, you can write non-instrumented tests for the presenter (even without Robolectric), running tests faster on your local JVM and without an emulator.

What if I need the Context?

Well, get rid of it. In cases like this, you should ask yourself why you need the context. You may need the context to access shared preferences or resources, for example. But you shouldn’t do that in the presenter: you should access to resources in the view and to preferences in the model. These are just two simple examples, but I can bet that the most of the times it is just a problem of wrong responsibilities.

By the way, the dependency inversion principle helps a lot in cases like this, when you need to decouple an object.

3. Write a contract to describe the interaction between View and Presenter:

When you are going to write a new feature, it is a good practice to write a contract at first step. *The contract describes the communication between view and presenter, it helps you to design in a cleaner way the interaction.

I like to use the solution proposed by Google in the Android Architecture repository: it consists of an interface with two inner interfaces, one for the view and one for the presenter.

Let’s make an example.

public interface SearchRepositoriesContract {
  interface View {
    void addResults(List<Repository> repos);
    void clearResults();
    void showContentLoading();
    void hideContentLoading();
    void showListLoading();
    void hideListLoading();
    void showContentError();
    void hideContentError();
    void showListError();
    void showEmptyResultsView();
    void hideEmptyResultsView();
  }
  interface Presenter extends BasePresenter<View> {
    void load();
    void loadMore();
    void queryChanged(String query);
    void repositoryClick(Repository repo);
  }
}

Just reading the method names, you should be able to understand the use case I’m describing with this contract.

As you can see from the example, view methods are so simple that suggest there isn’t any logic except UI.

The View contract:

Like I said before, the view is implemented by an Activity (or a Fragment). The presenter must depend on the View interface and not directly on the Activity: in this way, you decouple the presenter from the view implementation (and then from the Android platform) respecting the D of the SOLID principles: “Depend upon Abstractions. Do not depend upon concretions”.

We can replace the concrete view without changing a line of code of the presenter. Furthermore, we can easily unit-test presenter by creating a mock view.

The Presenter contract:

Wait. Do we really need a Presenter interface?

Actually no, but I would say yes.

There are two different schools of thought about this topic.

Some people think you should write the Presenter interface because you are decoupling the concrete view from the concrete presenter.

However, some developers think you are abstracting something that is already an abstraction (of the view) and you don’t need to write an interface. Moreover, you will likely never write an alternative presenter, then it would be a waste of time and lines of code.

Anyway, having an interface could help you to write a mock presenter, but if you use tools like Mockito you don’t need any interface.

Personally, I prefer to write the Presenter interface for two simple reasons (besides those I listed before):

  • I’m not writing an interface for the presenter. I’m writing a Contract that describes the interactions between View and Presenter. And having the rules of both “contractual parties” in the same file sounds very clean to me.

  • It isn’t a real effort.

4. Define a naming convention to separate responsibilities:

The presenter may generally have two categories of methods:

  • Actions (load() for example): they describes what the presenter does.

  • User events (queryChanged(...) for example): they are actions triggered by the user like “typing in a search view” or “clicking on a list item”.

More actions you have, more logic will be inside the view. User events, instead, suggest that they leave to the presenter the decision of what to do. For instance, a search can be launched only when at least a fixed number of characters are typed by the user. In this case, the view just calls the queryChanged(...) method and the presenter will decide when to launch a new search applying this logic.

loadMore() method, instead, is called when a user scrolls to the end of the list, then presenter loads another page of results. This choice means that when a user scrolls to the end, view knows that a new page has to be loaded. To “reverse” this logic, I could have named the method onScrolledToEnd() letting concrete presenter decide what to do.

What I’m saying is that during the “contract design” phase, you must decide for each user event, what is the corresponding action and who the logic should belong to.

5. Do not create Activity-lifecycle-style callbacks in the Presenter interface:

With this title I mean the presenter shouldn’t have methods like onCreate(...), onStart(), onResume() and their dual methods for several reasons:

  • In this way, the presenter would be coupled in particular with the Activity lifecycle. What if I want to replace the Activity with a Fragment? When should I call the presenter.onCreate(state) method? In fragment’s onCreate(...), onCreateView(...) or onViewCreated(...)? What if I’m using a custom view?

  • The presenter shouldn’t have a so complex lifecycle. The fact that the main Android components are designed in this way, doesn’t mean that you have to reflect this behavior everywhere. If you have the chance to simplify, just do it.

Instead of calling a method of the same name, in an Activity lifecycle callback, you can call a presenter’s action. For example, you could call load() at the end of Activity.onCreate(...).

6. Presenter has a 1-to-1 relation with the view:

The presenter doesn’t make sense without a view. It comes with the view and goes when the view is destroyed. It manages one view at a time.

You can handle the view dependency in the presenter in multiple ways. One solution is to provide some methods like attach(View view) and detach() in the presenter interface, like the example shown before. The problem of this implementation is that the view is nullable, then you have to add a null-check every time presenter needs it. This could be a bit boring…

I said that there is a 1-to-1 relation between view and presenter. We can take advantage of this. The concrete presenter, indeed, can take the view instance as a constructor parameter (This is the preferred method. Android Architecture Blueprint use this too). By the way, you may need anyway a method to subscribe presenter to some events. So, I recommend to define a method start() (or something similar) to run presenter’s business.

What about detach()?

If you have a method start(), you may need at least a method to release dependencies. Since we called the method that lets presenter subscribe some events start(), I’d call this one stop().

public interface BasePresenter<V> {
  void attach(V view);
  void detach();
}

BasePresenterAttach.java
public interface BasePresesnter {
  void start();
  void stop();
}

BasePresenterStart.java

7. Do not save the state inside the presenter:

I mean using a Bundle. You can’t do this if you want to respect the point 2. You can’t serialize data into a Bundle because presenter would be coupled with an Android class.

I’m not saying that the presenter should be stateless because I’d be lying. In the use case I described before, for instance, the presenter should at least have the page number/offset somewhere.

So, you must retain the presenter, right?

8. No. Do not retain the presenter:

I don’t like this solution mainly because I think that presenter is not something we should persist, it is not a data class, to be clear.

Some proposals provide a way to retain presenter during configuration changes using retained fragments or Loaders. Apart from personal considerations, I don’t think that this is the best solution. With this trick, the presenter survives to orientation changes, but when Android kills the process and destroys the Activity, the latter will be recreated together with a new presenter. For this reason, this solution solves only half of the problem.

So...?

9. Provide a cache for the Model to restore the View state:

In my opinion, solving the “restore state” problem requires adapting a bit the app architecture. A great solution in line with this thoughts was proposed in this article. Basically, the author suggests caching network results using an interface like a Repository or anything with the aim to manage data, scoped to the application and not to the Activity (so that it can survive to orientation changes).

This interface is just a smarter Model. The latter should provide at least a disk-cache strategy and possibly an in-memory cache. Therefore, even if the process is destroyed, the presenter can restore the view state using the disk cache.

The view should concern only about any necessary request parameters to restore the state. For instance, in our example, we just need to save the query.

Now, you have two choices:

  • You abstract this behavior in the model layer so that when presenter calls repository.get(params), if the page is already in cache, the data source just returns it, otherwise the APIs are called.

  • You manage this inside the presenter adding just another method in the contract to restore the view state. restore(params), loadFromCache(params) or reload(params) are different names that describe the same action, you choose.

Android MVP Q&A:

Q: Should we create a method onActivityResult() in Presenter to help Activity to handle those result?

I wouldn’t create a method onActivityResult, in the presenter because, like you said, it’s view responsibility.

Sometimes you need to do something in the presenter right after the onActivityResult. In that case, you handle the result in the view and call some presenter method to run the action you need.


Let’s say that i have a button. When i clik it, it calls getLastKnownLocation() from presenter. To get location i need an activity, becouse i have to check permissions, also i need activity/context to create GoogleApiClient. Is there any better aproach than passing an activity to the presenter?

You can do that by hiding this behavior behind an interface to get the location, let’s say LocationService. The latter, would depend on the Activity/Context. Through dependency injection, you could inject this service into presenter decoupling the latter from the Activity.

View calls presenter.onButtonClick()``, presenter calls locationService.getLocation()`.


how do you deal with RecyclerView’s adapters, especially if the items displayed need some additional preprocessing? I saw both the solution where each ViewHolder have its own presenter and the one where the main presenter feeds the view with the list of preprocessed items. Do you follow any of them, or you have some way of your own?

I prefer not to create a presenter for each ViewHolder. I think we should use MVP only if there is a significant logic to handle.

Most of the time the “main presenter” just feeds the view with the list of items. In the example I provided, you can see the method addResults(List<Repository> repos). That Repository class should be a convenient model class to be used by the Adapter. Did you mean this with “additional preprocessing”?


  • is there consensus on the naming conventions used of the functions in the presenter and view interface within the contract? I feel like readability will go up ALOT once you know which name corresponds to a presenter or not (for example refresh/fetch/update are all along the same lines but could be unique for either the presenter or the view.
  • Suppose I want to start refreshing multiple graphs in a single view from the presenter, what is the easiest way to do this ?
  • Actually you should distinguish view methods from presenter ones just because the view methods should be verbs about something to show/hide (showProgressBar, showGraph,…). The presenter methods, as I explained in the article, should be actions (load, fetch,..) or user interactions (queryChanged, submit,…).

  • If you have to add some graphs to the view, you could define a method in the view named addGraph(Graph graph). The presenter should have the responsibility to create the Graph objects. RxJava could be useful but it is not essential. You can do this also with AsyncTasks.


What about RecyclerView ViewHolders with complex logic like comments for video, which can be deleted/editted/created/quoted e.t.c.? I’ve read your answers for Marcin Jedynak about it, but the question is: Where to store List<CommentPresenter>? And who needs to manage them?

Let’s say, order of actions is:

View calls presenter.onLoadMore();

Presenter calls commentsRepository.loadNew(lastLoadTimestamp);

Presenter calls view.updateComments(commentsChanges); // commentsChanges has info about changes (edition/creation/deletion) of all comments from lastLoadTimestamp

So what happening now? Does View manages list of presenters? (then it will be Active View) Or does presenter store presenters for every ViewHolder and use DiffUtil to handle changes in it?

I don’t think that the “main” presenter should have a reference to the ViewHolders’ presenters.

If your ViewHolders are so complex, what do you think about creating a custom view for each one of them with its own presenter? This way, each presenter is handled by the related ViewHolder/CustomView.

class ViewHolder1 -> class CustomView1 -> class Presenter1
class ViewHolder2 -> class CustomView2 -> class Presenter2
…
class ViewHolderN -> class CustomViewN -> class PresenterN

Of course, an instance of ViewHolderX has an instance of the CustomViewX with its own instance of PresenterX with 1 ≤ X ≤ N.

What do you think?

It would be a good idea, will it not cause state loss while scrolling due to reusing old View for new chunk of data? Seems like either Presenter must be written with pretty strict data-change policy, either it must completely drop its old Presenter or new data arrival.

Yes… Presenter could survive and “repopulate” itself with a new bind. Seems that the attach() and detach() fit better in this case.

No, I’m wrong. Actually the View is the same so attach() and detach() are useless again in this case. You should provide just a way to pass new data to Presenter.

I don’t particularly like this solution, but since creating a Presenter for each onBindViewHolder is not recommended for performance reasons, I’d prefer the “efficient” solution to the “clean” one :)


What about if the presenter need to choose string from strings.xml? The string chosen would depends on the state and it may have some parameters in it. It would need context to access the getString method.

It isn’t presenter’s responsibility. The view should access to resources, instead. You should move this kind of logic inside the view.

For most of the cases, yes. But sometimes the string to be displayed is determined by some value of other variables. Wouldn’t this be the business logic?

I think that choosing what string to show is presentation/view logic.

The fact that a string depends on something else, doesn’t mean that you can’t move the string resolution in the view maintaining business logic in the presenter.


My problem is decoupling the Presenter from Android Platform. How can I deal with frameworks like Loaders, Cursors, Content Provider without Presenters knows about them?

There is already a debate about this topic here. I believe that there are such things we can’t abstract, or at least, abstracting them is an excessive and vain effort. MVP doesn’t solve every problem.

If you think it isn’t worth it, don’t do it.


How the model will get the CONTEXT , If required?

You could provide the Context in the model constructor, for example.


I want to add swipe functionality to the items in RecyclerView to delete items.

Can you please tell me where should I put the abstract method for it? In the Presenter or the View interface of the Contract?

I think that the view should listen to the swipe event and then call a method on the presenter like itemSwiped. This method should delete the item and notify the view. So, I would define this itemSwiped method in the Presenter contract and a method to remove the item in the View contract.


My question is about framework independence for presenters. What if I need to run some simple validation in my presenter, like check if the email is valid an the password is not empty and I want to use handy TextUtils class? It would instantly make my presenter framework-aware and break the entire idea, but at the same time I hardly imagine implementing TextUtils myself just to not break the pattern. The only way I see is using some 3rd-party text utils library, like apache-commons which is Android-independent but the questions remains open. What do you use for text validations in your presenters?

Yeah, it’s really frustrating, it’s true. Using apache commons or creating your utils class can be both solutions. Or if you use Kotlin, you can solve this problem with extension functions, I think… Personally, I use my TextUtils class.

It’s your decision: you can run JVM tests if you use one of these solutions, otherwise you have to run instrumented tests.


I was writing an app component where I had implemented two screens where I am implementing View using Fragments (say FragmentA and FragmentB). Now, I start my application using an Activity which first loads FragmentA. Now, based on a user action in this view, I want to replace the current fragment to FragmentB in the current activity. Which component should talk to the Activity in this case; the Presenter or the View (i.e. the Fragment)?

If you have corresponding PresenterA and PresenterB for FragmentA and FragmentB, the PresenterA shouldn’t talk directly to the Activity, but the Fragment should do that. In my opinion, the fact that the View is a Fragment inside an Activity and it has to be replaced with another Fragment, isn’t Presenter’s responsibility.


If the presenter shouldn’t know anything about the Android framework, how can it take the view instance as a constructor parameter? Shouldn’t it take the contract interface instance as a parameter, like SearchRepositoriesContract.View?

I meant exactly what you said, indeed.


What if the Model uses, for example, the Context class, to open a SQLite Database? I should have the Context somewhere, and in my case, I think that Context could be in the Presenter.

If I use my Model too much and I need to open the SQLite DB too much, I think that’s not correct to ask the View ‘hey, give me your Context’ every time I want to get and show some info.

What do you think?

The presenter should never ask the Context to anyone. The context should never appear in the presenter code in order to make it non-instrumented unit-testable.

If you need the Context to interact with a database, you should hide this behavior behind an interface.

Let’s say your current class that deals with the db is UsersDbHelper. You should just create an interface UsersRepository (UserModel, or whatever you want) that uses UsersDbHelper to fetch users. Injecting a UsersRepository object into the presenter, removes the context dependency from the latter.

But, If you do what you say, the Context has to be in UsersRepository (or in the Model), right? So, how the UsersRepository gets the Context? The UsersRepository, in some way, knows the View? Or the Presenter gives the UserRepository the Context?

I mean, someone has to know the Context, and the Model cannot have communication with the View, so…

Dependency injection is the answer. UsersRepository should take Context as constructor parameter.


Say I have an Activity that binds and unbinds a Service in onStart/onStop respectively. Input comes from the user and needs to be processed by the bound service. What would be your approach in this case to do it with MVP?

What I had in mind is having a setter method on the Presenter for the service interface and call it once the service is connected/disconnected. This way I can still test the Presenter without any framework dependency since the Presenter will be working with an interface of the service.

What do you think about that? Is there a better way?

I wrote an article about my expierence with Android Bound Services and MVP.

I think Services are an Android framework detail really difficult to abstract. To be honest, I’ve never faced this problem, so I wouldn’t give you a probably wrong advice.

I can just say that your solution looks quite good to me from the “MVP perspective”.


My thoughts related to MVP are similar, but i’m not sure about approach to cache data in app scoped mechanism (anyway, i have to try that Store stuff from article you linked to).. What about cache invalidation? For example —user enters activity for the second time and got cached data (cuz previously request was saved). I suppose that there are plenty ways to achieve that but I didn’t find any simple and elegant solution ;)

Could you give some advices about that problem, please? Or maybe it isn’t a problem at all and I don’t understand something.. :)

Well, it depends on whether your network service allows you to have at least a short-term cache. In that case you could just define a cache expiration time. In this way, when user comes back to the activity and the cache is still valid, gets old data and presenter continues its work like user never left the app.

If the cache is expired, instead, depends on where you decide to put the logic:

  • If it is in the model, the latter should automatically call the APIs with the same request params returning fresh data.
  • If the logic is inside the presenter, means that there should be a method model.cache(params). When the cache is expired, this method could launch an exception or return any result that describes there is a cache miss/expiration. Then presenter should call model again with the same parameters, but this time using the method that submits the network call.

In a case like the example I provided, you can also invalidate the cache user submits a new search.


"If you are using the Clean architecture, instead, the Model could be an Interactor.""

Why Model could be an Interactor? I understand that Interactor executes Use Cases in the Domain layer; and then it should be run by the Presenter. I guess Model is updated with the info got from the Repository via Presenter.

I meant that sometimes the presenter doesn’t depend directly on the real model, but on an interface (the interactor) that communicates with other modules in charge of that.

It is just a way to separate the three responsibilities of MVP. The activity/fragment is the view, the concrete presenter is … the presenter… and the model is everything that allows presenter to query and update the data.

Of course, Repository manages the model, but the direct dependency of presenter is the interactor.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment