There are a lot of posts talking about how to correctly implement MVP pattern over Android. So why another one?
Well, I want to tell you my experience developing a library to simplify MVP implementation for those ones who recently start working on Android and are interested in correctness over code.
About 3 months ago or more, I have released MVP Helper Library. MVP Helpers is aimed to provide a simpler way to develop your Android Apps by following a simple series of concepts around MVP and inherit from a set of helper classes.
MVP Helpers started as an abstraction over an application that I was implementing for a Financial Company. After finish the creation of that App, I realize that parts of the code where similar among different Activities and Fragments.
My interest for cleaner code began since I started to work with Android (About 3 years ago). In the old times we use to do much over the Activities, we used to make hard the apps to scale when new features were requested.
Because of that, I read about different patterns like MVC, MVVM and MVP. Every pattern has different pros and cons. I have implemented all of them, but the one I really like was MVP. That pattern let me decouple easily the code, and also refactor different apps faster, was completely easier to reason, and also easier to follow, improve code modularity, and make unit testing so so simpler.
Well, coming back to MVP Helpers, the concepts behind my library are similar to MVP and are the following ones:
MVP Helpers Approach
Well, you have seen the basis around MVP Helpers, now lets go to the code. Follow this steps to get started:
allprojects {repositories {...maven {url "https://jitpack.io"}}}
dependencies {compile "com.github.BlackBoxVision:mvp-helpers:v0.2.0"}
public interface DetailsView extends BaseView {void onInfoReceived(@NonNull String info);void onInfoError(@NonNull String error);}
Create an Interactor class by extending from BaseInteractor. When you extend from BaseInteractor you get a few cool methods to simplify dealing with concurrency:
public final class DetailsInteractor extends BaseInteractor {public void retrieveDetailsFromService(String id, OnSuccessListener<String> sListener, OnErrorListener<String> eListener) {runOnBackground(() -> {final String data = Helpers.findSomeDataById(id);runOnUiThread(() -> {if (data != null) {sListener.onSuccess(data);} else {eListener.onError("Ups, something went wrong");}});});}}
Create a Presenter by inheriting from BasePresenter. BasePresenter gives to you a few fancy methods to deal with view attach/detach and some callbacks attach/detach is performed so you can do an action over it:
public final class DetailsPresenter extends BasePresenter<DetailsView> {private DetailsInteractor interactor;@Overrideprotected void onViewAttached(@NonNull DetailsView view) {interactor = new DetailsInteractor();}@Overrideprotected void onViewDetached() {interactor = null;}public void findRequiredInformation(@NonNull String id) {if (isViewAttached()) {interactor.retrieveDetailsFromService(id, this::onSuccess, this::onError);}}private void onSuccess(@NonNull String information) {if (isViewAttached()) {getView().onInfoReceived(information);}}private void onError(@NonNull String errorMessage) {if (isViewAttached()) {getView().onInfoError(errorMessage);}}}
class DetailsPresenterFactory implements PresenterFactory<DetailsPresenter> {@Overridepublic DetailsPresenter create() {return new DetailsPresenter();}}
Finally you have to add connect this classes to your Activity/Fragment. To make that you can inherit from BaseActivity/BaseFragment. With this custom Activity/Fragment you don’t have to take care about Presenter creation/destruction.
public final class DetailsFragment extends BaseFragment<DetailsPresenter, DetailsView> implements DetailsView {@Overrideprotected DetailsPresenterFactory createPresenterFactory() {return new DetailsPresenterFactory();}@LayoutRes@Overrideprotected int getLayout() {return R.layout.fragment_details;}@Overrideprotected void onPresenterCreated(@NonNull DetailsPresenter presenter) {//Do something when presenter it's createdgetPresenter().getInformationFromId("ssdWRGD132");}@Overrideprotected void onPresenterDestroyed() {//Do something when presenter is removed, this method is called in onDestroy}@Overridevoid onInfoReceived(@NonNull String information) {Toast.makeText(getContext(), information, Toast.LENGTH_SHORT).show();}@Overridevoid onInfoError(@NonNull String errorMessage) {Toast.makeText(getContext(), errorMessage, Toast.LENGTH_SHORT).show();}}
Subscribe for latest updates
Sign Up for our newsletter and get notified when we publish new articles for free!