{"id":20995113,"url":"https://github.com/blackboxvision/mvp-helpers","last_synced_at":"2025-05-14T21:31:01.430Z","repository":{"id":79966435,"uuid":"74705553","full_name":"BlackBoxVision/mvp-helpers","owner":"BlackBoxVision","description":"♻️Helper classes to build Android Apps through MVP pattern in a faster way","archived":false,"fork":false,"pushed_at":"2017-05-21T23:03:11.000Z","size":2744,"stargazers_count":42,"open_issues_count":3,"forks_count":12,"subscribers_count":6,"default_branch":"master","last_synced_at":"2025-04-02T23:34:31.170Z","etag":null,"topics":["android","java","library","mvp-architecture","mvp-clean","mvp-pattern"],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/BlackBoxVision.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null}},"created_at":"2016-11-24T21:16:05.000Z","updated_at":"2021-03-17T18:14:19.000Z","dependencies_parsed_at":null,"dependency_job_id":"640fd956-d471-437f-a9af-88ce248204f1","html_url":"https://github.com/BlackBoxVision/mvp-helpers","commit_stats":null,"previous_names":[],"tags_count":6,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/BlackBoxVision%2Fmvp-helpers","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/BlackBoxVision%2Fmvp-helpers/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/BlackBoxVision%2Fmvp-helpers/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/BlackBoxVision%2Fmvp-helpers/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/BlackBoxVision","download_url":"https://codeload.github.com/BlackBoxVision/mvp-helpers/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254230817,"owners_count":22036248,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["android","java","library","mvp-architecture","mvp-clean","mvp-pattern"],"created_at":"2024-11-19T07:21:46.050Z","updated_at":"2025-05-14T21:30:58.229Z","avatar_url":"https://github.com/BlackBoxVision.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cimg src=\"https://github.com/BlackBoxVision/mvp-helpers/blob/master/art/logo.png\" width=\"425px\" height=\"125px\"\u003e\n\u003e Helper classes to build Android Apps through MVP pattern in a faster way\n\n[![License: MIT](https://img.shields.io/badge/License-MIT-brightgreen.svg)](https://opensource.org/licenses/MIT) [![Android Arsenal](https://img.shields.io/badge/Android%20Arsenal-MVP%20Helpers-brightgreen.svg?style=flat)]() [![](https://jitpack.io/v/BlackBoxVision/mvp-helpers.svg)](https://jitpack.io/#BlackBoxVision/mvp-helpers) [![Build Status](https://travis-ci.org/BlackBoxVision/mvp-helpers.svg?branch=master)](https://travis-ci.org/BlackBoxVision/mvp-helpers)\n\n**This library exposes a minimal API, that should help you to build well architected Android Apps. ¡Check the following steps to get up and running!**\n\n## Installation\n\nActually I don't have this library in **JCenter/Maven Central**, so if you want to use, follow the instructions. The library is distributed for Java and Kotlin. Looking for Kotlin variant? [Go here](https://github.com/BlackBoxVision/mvp-helpers/tree/kotlin)\n\n**Gradle**\n\n- Add it in your root build.gradle at the end of repositories:\n```gradle\nallprojects {\n\trepositories {\n\t\t...\n\t\tmaven { \n\t\t\turl \"https://jitpack.io\" \n\t\t}\n\t}\n}\n```\n\n- Add the dependency:\n```gradle\ndependencies {\n\t compile 'com.github.BlackBoxVision:mvp-helpers:v0.2.0'\n}\n```\n\n**Maven**\n\n- Add this line to repositories section in pom.xml:\n```xml\n\u003crepositories\u003e\n\t\u003crepository\u003e\n\t   \u003cid\u003ejitpack.io\u003c/id\u003e\n\t\t \u003curl\u003ehttps://jitpack.io\u003c/url\u003e\n\t\u003c/repository\u003e\n\u003c/repositories\u003e\n```\n- Add the dependency:\n```xml\n\u003cdependency\u003e\n  \u003cgroupId\u003ecom.github.BlackBoxVision\u003c/groupId\u003e\n  \u003cartifactId\u003emvp-helpers\u003c/artifactId\u003e\n\t\u003cversion\u003ev0.2.0\u003c/version\u003e\n\u003c/dependency\u003e\n```\n\n**SBT**\n\n- Add it in your build.sbt at the end of resolvers:\n```sbt\n  resolvers += \"jitpack\" at \"https://jitpack.io\"\n```\n\n- Add the dependency:\n```sbt\n  libraryDependencies += \"com.github.BlackBoxVision\" % \"mvp-helpers\" % \"v0.2.0\"\t\n```\n\n## Core Concepts\n\nThe concepts behind this library are the following ones: \n- **View** → The **View** is an interface that contains methods related to UI interaction. Those methods should be implemented in your **Activity, Fragment or View**.\n\n- **Interactor** → The **Interactor** is the class that do the hard work, all the blocking operations like **I/O, Networking, Database** Intectations should be done here. \n\n- **Presenter** → The **presenter** acts as a middle man between the **Interactor** and the **View**.\n\n![](https://github.com/BlackBoxVision/mvp-helpers/blob/master/art/mvp-helpers-architecture.png)\n\n## Usage example\n\nThe usage is really simple: \n\n**1** - Create your **View** interface by extending the [**BaseView**](https://github.com/BlackBoxVision/mvp-helpers/blob/master/library/src/main/java/io/blackbox_vision/mvphelpers/logic/view/BaseView.java). **BaseView** is an empty interface that acts as water mark for the **Presenter**.\n\n```java\npublic interface DetailsView extends BaseView {\n\n    void onInfoReceived(@NonNull Bundle information);\n\n    void onInfoError(@NonNull String errorMessage);\n}\n```\n\n**2** - Create an **Interactor** class by extending the [**BaseInteractor**](https://github.com/BlackBoxVision/mvp-helpers/blob/master/library/src/main/java/io/blackbox_vision/mvphelpers/logic/interactor/BaseInteractor.java) class. The **BaseInteractor** provides you a set of helper methods to deal with **background execution and UIThread interaction**. The methods are the following ones: \n\n- **runOnUiThread** → use it when you need to post data to the main thread.\n- **runOnBackground** → use it when you need to make background processing. \n- **runOnBackground** → use it when you need to make a scheduled task. \n- **cancelTask** → use it when you want to cancel a scheduled task. \n\n```java\n//This example uses Java 8 features, I assume the usage of retrolambda\npublic final class DetailsInteractor extends BaseInteractor {\n\n    public void retrieveDetailsFromService(@NonNull final String id, @NonNull final OnSuccessListener\u003cBundle\u003e successListener, @NonNull final OnErrorListener\u003cString\u003e errorListener) {\n        runOnBackground(() -\u003e {\n            //Getting data from somewhere\n            final Bundle data = MockUtils.getMockedData(id);\n\n            runOnUiThread(() -\u003e {\n                if (data != null) {\n                    successListener.onSuccess(data);\n                } else {\n                    errorListener.onError(\"Ups, something went wrong\");\n                } \n            });\n        });\n    }\n}\n```\n\n**3** - Create a **Presenter** class by extending the [**BasePresenter**](https://github.com/BlackBoxVision/mvp-helpers/blob/master/library/src/main/java/io/blackbox_vision/mvphelpers/logic/presenter/BasePresenter.java) class. The **BasePresenter** provides you with a set of helper methods to deal with **View** management. The methods are the following ones:\n\n- **isViewAttached** → check if you have set the view to the presenter, returns to you a boolean value that you should handle in your presenter implementation. \n- **attachView** → add the view to the presenter, so you can start to handle the cycle of view - presenter - interactor interaction.\n- **detachView** → dereference the view, setting it to null. This method should be called in the onDestroy method in case of use in Activity, and onDestroyView in case of Fragment usage. \n- **getView** → simple getter, to make your access to the view defined more cleaner.\n- **onViewAttached** → callback fired when the view is attached to the presenter, it gives you the view so you can start doing something like restoring state, instantiating the interactors.  \n- **onViewDetached** → callback fired when the view is detached from the presenter, in this place you can dereference the objects you won't use anymore. \n\n```java\n//I use method references from Java 8 to point the callbacks to interactor, I assume a working project with Retrolambda\npublic final class DetailsPresenter extends BasePresenter\u003cDetailsView\u003e {\n    private DetailsInteractor interactor;\n    \n    @Override\n    protected void onViewAttached(@NonNull DetailsView view) {\n        interactor = new DetailsInteractor();\n    }\n\n    @Override\n    protected void onViewDetached() {\n        interactor = null;\n    }\n\n    public void findRequiredInformation(@NonNull String id) {\n        if (isViewAttached()) {\n            interactor.retrieveDetailsFromService(id, this::onSuccess, this::onError);\n        }\n    }\n\n    private void onSuccess(@NonNull Bundle information) {\n        if (isViewAttached()) {\n            getView().onInfoReceived(information);\n        }\n    }\n\n    private void onError(@NonNull String errorMessage) {\n        if (isViewAttached()) {\n            getView().onInfoError(errorMessage);\n        }\n    }\n}\n```\n\n**4** - Create a custom **PresenterFactory** class to provide the presenter instance. You should implement the [**PresenterFactory**](https://github.com/BlackBoxVision/mvp-helpers/blob/master/library/src/main/java/io/blackbox_vision/mvphelpers/logic/factory/PresenterFactory.java) interface. \n\n**Now we have to create a Factory, because I have recently implemented a way to not loose presenter when configuration changes. The BaseActivity/BaseFragment use a Loader to provide the Presenter instance, Android Loaders can survive configuration changes, that's why I select them.** \n\n```java\nclass DetailsPresenterFactory implements PresenterFactory\u003cDetailsPresenter\u003e {\n\t\n\t@Override\n\tpublic DetailsPresenter create() {\n\t\treturn new DetailsPresenter();\n\t}\n}\n```\n\n**5** - Attach this cycle with Android specific classes. You can choice an **Activity/Fragment or also a custom view**. In this case I will show you an example with **Fragment** that inherits from [**BaseFragment**](https://github.com/BlackBoxVision/mvp-helpers/blob/master/library/src/main/java/io/blackbox_vision/mvphelpers/ui/fragment/BaseFragment.java)\n\nThe **BaseFragment** comes with a resumed lifecycle, and a set of methods to implement. The methods are the following ones:\n\n- **createPresenterFactory** → in this method you have to create an instance of PresenterFactory. \n- **getLayout** → in this method you have pass the id reference to the layout. \n- **getPresenter** → simple getter, to make your access to the presenter more cleaner.\n- **onPresenterCreated** → In this method you can start doing something with the presenter. **¡Now the View is attached automatically to the Presenter!**\n- **onPresenterDestroyed** → In this method you can do something, like saving app state. \n\n```java\npublic final class DetailsFragment extends BaseFragment\u003cDetailsPresenter, DetailsView\u003e implements DetailsView {\n    \n    @Override\n    protected DetailsPresenterFactory createPresenterFactory() {\n      \treturn new DetailsPresenterFactory();\n    }\n    \n    @LayoutRes\n    @Override\n    protected int getLayout() {\n      \treturn R.layout.fragment_details;\n    }\n    \n    @Override\n    protected void onPresenterCreated(@NonNull DetailsPresenter presenter) {\n    \t//Do something when presenter it's created\n\t    getPresenter().getInformationFromId(\"ssdWRGD132\");\n    }\n    \n    @Override\n    protected void onPresenterDestroyed() {\n\t    //Do something when presenter is removed, this method is called in onDestroy\t\n    }\n    \n    @Override\n    void onInfoReceived(@NonNull Bundle information) {\n       Toast.makeText(getContext(), information.toString(), Toast.LENGTH_SHORT).show();\n    }\n    \n    @Override\n    void onInfoError(@NonNull String errorMessage) {\n       Toast.makeText(getContext(), errorMessage, Toast.LENGTH_SHORT).show();\n    }\n} \n```\n\n## Advise about ButterKnife\n\nFrom version **0.2.0 of this library**, I have decided to remove butterKnife, in order to not force any dev to use butterKnife. \n\n## Issues \n\nIf you found a bug, or you have an answer, or whatever. Please, open an [issue](https://github.com/BlackBoxVision/mvp-helpers/issues). I will do the best to fix it, or help you. \n\n## Contributing\n\nOf course, if you see something that you want to upgrade from this library, or a bug that needs to be solved, **PRs are welcome!**\n\n## Release History\n\n* **0.2.0**\n  * **CHANGE**: **BasePresenter** has now two new callbacks, to be notified about **view attachment/detachment**. \n  * **CHANGE**: **BaseActivity/BaseFragment** has now two new callbacks to be notified about **presenter creation/destruction**, also, **addPresenter** callback has been replace with **createPresenterFactory**\n  * **CHANGE**: Added **PresenterFactory** interface to create custom factories to provide presenter instances\n  * **CHANGE**: Added **PresenterLoader**, an Android Loader, that provides the presenter instance and survives configuration changes. \n  * **BUG FIX**: Fixed issue with **BaseInteractor runOnBackground method**, this method was calling **executor.isTerminated** instead of calling **executor.isShutdown**, this produce a RuntimeException, because of troubles with ThreadPool reuse. Also, the methods have been refactored, to use a **ExecutorService** to get more control instead of an **Executor**.\n\n* **0.1.0** \n  * **CHANGE**: Folder refactor under **UI package**\n  * **CHANGE**: Modified **BasePresenter** method **registerView** to **attachView** in order to get more consistence\n  * **CHANGE**: Added new **runOnBackground** version in **BaseInteractor** that uses a ScheduledExecutorService and also cancel method to stop execution\n  * **CHANGE**: Added Custom Views to extend **BaseRelativeLayout, BaseFrameLayout and BaseLinearLayout**\n* **0.0.3**\n  * **CHANGE**: Removed **ButterKnife** annotation processor\t\n  * **CHANGE**: Rename **mvphelper** library to library\n* **0.0.2**\n  * **CHANGE**: Minor updates\n* **0.0.1**\n  * Work in progress\n\n## License\n\nDistributed under the **MIT license**. See [LICENSE](https://github.com/BlackBoxVision/mvp-helpers/blob/master/LICENSE) for more information.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fblackboxvision%2Fmvp-helpers","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fblackboxvision%2Fmvp-helpers","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fblackboxvision%2Fmvp-helpers/lists"}