项目作者: BlackBoxVision

项目描述 :
♻️Helper classes to build Android Apps through MVP pattern in a faster way
高级语言: Java
项目地址: git://github.com/BlackBoxVision/mvp-helpers.git
创建时间: 2016-11-24T21:16:05Z
项目社区:https://github.com/BlackBoxVision/mvp-helpers

开源协议:MIT License

下载


Helper classes to build Android Apps through MVP pattern in a faster way

License: MIT Android Arsenal Build Status

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!

Installation

Actually 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

Gradle

  • Add it in your root build.gradle at the end of repositories:

    1. allprojects {
    2. repositories {
    3. ...
    4. maven {
    5. url "https://jitpack.io"
    6. }
    7. }
    8. }
  • Add the dependency:

    1. dependencies {
    2. compile 'com.github.BlackBoxVision:mvp-helpers:v0.2.0'
    3. }

Maven

  • Add this line to repositories section in pom.xml:
    1. <repositories>
    2. <repository>
    3. <id>jitpack.io</id>
    4. <url>https://jitpack.io</url>
    5. </repository>
    6. </repositories>
  • Add the dependency:
    1. <dependency>
    2. <groupId>com.github.BlackBoxVision</groupId>
    3. <artifactId>mvp-helpers</artifactId>
    4. <version>v0.2.0</version>
    5. </dependency>

SBT

  • Add it in your build.sbt at the end of resolvers:

    1. resolvers += "jitpack" at "https://jitpack.io"
  • Add the dependency:

    1. libraryDependencies += "com.github.BlackBoxVision" % "mvp-helpers" % "v0.2.0"

Core Concepts

The concepts behind this library are the following ones:

  • View → The View is an interface that contains methods related to UI interaction. Those methods should be implemented in your Activity, Fragment or View.

  • 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.

  • Presenter → The presenter acts as a middle man between the Interactor and the View.

Usage example

The usage is really simple:

1 - Create your View interface by extending the BaseView. BaseView is an empty interface that acts as water mark for the Presenter.

  1. public interface DetailsView extends BaseView {
  2. void onInfoReceived(@NonNull Bundle information);
  3. void onInfoError(@NonNull String errorMessage);
  4. }

2 - Create an Interactor class by extending the BaseInteractor class. The BaseInteractor provides you a set of helper methods to deal with background execution and UIThread interaction. The methods are the following ones:

  • runOnUiThread → use it when you need to post data to the main thread.
  • runOnBackground → use it when you need to make background processing.
  • runOnBackground → use it when you need to make a scheduled task.
  • cancelTask → use it when you want to cancel a scheduled task.
  1. //This example uses Java 8 features, I assume the usage of retrolambda
  2. public final class DetailsInteractor extends BaseInteractor {
  3. public void retrieveDetailsFromService(@NonNull final String id, @NonNull final OnSuccessListener<Bundle> successListener, @NonNull final OnErrorListener<String> errorListener) {
  4. runOnBackground(() -> {
  5. //Getting data from somewhere
  6. final Bundle data = MockUtils.getMockedData(id);
  7. runOnUiThread(() -> {
  8. if (data != null) {
  9. successListener.onSuccess(data);
  10. } else {
  11. errorListener.onError("Ups, something went wrong");
  12. }
  13. });
  14. });
  15. }
  16. }

3 - Create a Presenter class by extending the BasePresenter class. The BasePresenter provides you with a set of helper methods to deal with View management. The methods are the following ones:

  • 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.
  • attachView → add the view to the presenter, so you can start to handle the cycle of view - presenter - interactor interaction.
  • 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.
  • getView → simple getter, to make your access to the view defined more cleaner.
  • 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.
  • onViewDetached → callback fired when the view is detached from the presenter, in this place you can dereference the objects you won’t use anymore.
  1. //I use method references from Java 8 to point the callbacks to interactor, I assume a working project with Retrolambda
  2. public final class DetailsPresenter extends BasePresenter<DetailsView> {
  3. private DetailsInteractor interactor;
  4. @Override
  5. protected void onViewAttached(@NonNull DetailsView view) {
  6. interactor = new DetailsInteractor();
  7. }
  8. @Override
  9. protected void onViewDetached() {
  10. interactor = null;
  11. }
  12. public void findRequiredInformation(@NonNull String id) {
  13. if (isViewAttached()) {
  14. interactor.retrieveDetailsFromService(id, this::onSuccess, this::onError);
  15. }
  16. }
  17. private void onSuccess(@NonNull Bundle information) {
  18. if (isViewAttached()) {
  19. getView().onInfoReceived(information);
  20. }
  21. }
  22. private void onError(@NonNull String errorMessage) {
  23. if (isViewAttached()) {
  24. getView().onInfoError(errorMessage);
  25. }
  26. }
  27. }

4 - Create a custom PresenterFactory class to provide the presenter instance. You should implement the PresenterFactory interface.

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.

  1. class DetailsPresenterFactory implements PresenterFactory<DetailsPresenter> {
  2. @Override
  3. public DetailsPresenter create() {
  4. return new DetailsPresenter();
  5. }
  6. }

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

The BaseFragment comes with a resumed lifecycle, and a set of methods to implement. The methods are the following ones:

  • createPresenterFactory → in this method you have to create an instance of PresenterFactory.
  • getLayout → in this method you have pass the id reference to the layout.
  • getPresenter → simple getter, to make your access to the presenter more cleaner.
  • onPresenterCreated → In this method you can start doing something with the presenter. ¡Now the View is attached automatically to the Presenter!
  • onPresenterDestroyed → In this method you can do something, like saving app state.
  1. public final class DetailsFragment extends BaseFragment<DetailsPresenter, DetailsView> implements DetailsView {
  2. @Override
  3. protected DetailsPresenterFactory createPresenterFactory() {
  4. return new DetailsPresenterFactory();
  5. }
  6. @LayoutRes
  7. @Override
  8. protected int getLayout() {
  9. return R.layout.fragment_details;
  10. }
  11. @Override
  12. protected void onPresenterCreated(@NonNull DetailsPresenter presenter) {
  13. //Do something when presenter it's created
  14. getPresenter().getInformationFromId("ssdWRGD132");
  15. }
  16. @Override
  17. protected void onPresenterDestroyed() {
  18. //Do something when presenter is removed, this method is called in onDestroy
  19. }
  20. @Override
  21. void onInfoReceived(@NonNull Bundle information) {
  22. Toast.makeText(getContext(), information.toString(), Toast.LENGTH_SHORT).show();
  23. }
  24. @Override
  25. void onInfoError(@NonNull String errorMessage) {
  26. Toast.makeText(getContext(), errorMessage, Toast.LENGTH_SHORT).show();
  27. }
  28. }

Advise about ButterKnife

From version 0.2.0 of this library, I have decided to remove butterKnife, in order to not force any dev to use butterKnife.

Issues

If you found a bug, or you have an answer, or whatever. Please, open an issue. I will do the best to fix it, or help you.

Contributing

Of course, if you see something that you want to upgrade from this library, or a bug that needs to be solved, PRs are welcome!

Release History

  • 0.2.0

    • CHANGE: BasePresenter has now two new callbacks, to be notified about view attachment/detachment.
    • CHANGE: BaseActivity/BaseFragment has now two new callbacks to be notified about presenter creation/destruction, also, addPresenter callback has been replace with createPresenterFactory
    • CHANGE: Added PresenterFactory interface to create custom factories to provide presenter instances
    • CHANGE: Added PresenterLoader, an Android Loader, that provides the presenter instance and survives configuration changes.
    • 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.
  • 0.1.0

    • CHANGE: Folder refactor under UI package
    • CHANGE: Modified BasePresenter method registerView to attachView in order to get more consistence
    • CHANGE: Added new runOnBackground version in BaseInteractor that uses a ScheduledExecutorService and also cancel method to stop execution
    • CHANGE: Added Custom Views to extend BaseRelativeLayout, BaseFrameLayout and BaseLinearLayout
  • 0.0.3
    • CHANGE: Removed ButterKnife annotation processor
    • CHANGE: Rename mvphelper library to library
  • 0.0.2
    • CHANGE: Minor updates
  • 0.0.1
    • Work in progress

License

Distributed under the MIT license. See LICENSE for more information.