Giter Club home page Giter Club logo

mvp-helpers's Introduction

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

After working about 3 years with Android development, I learn a lot from the different projects I have made, a lot of mistakes, and a lot of lessons learned. About 1 year ago, or more, in Android, MVP become the selected pattern to make Android Apps. MVP makes your apps code more easier to follow, and also easier to reason.

This library, exposes a minimal API that I have abstracted during many projects. The classes that contain this library help me to speed app development, also, they clean my code a lot.

Check the following instructions under this README in order to get a project up and running with this simpler library.

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

###Java version

Gradle

  • Add it in your root build.gradle at the end of repositories:
allprojects {
	repositories {
		...
		maven { 
			url "https://jitpack.io" 
		}
	}
}
  • Add the dependency:
dependencies {
	 compile 'com.github.BlackBoxVision:mvp-helpers:v0.1.0'
}

Maven

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

SBT

  • Add it in your build.sbt at the end of resolvers:
  resolvers += "jitpack" at "https://jitpack.io"
  • Add the dependency:
  libraryDependencies += "com.github.BlackBoxVision" % "mvp-helpers" % "v0.1.0"	

###Kotlin version

  • Add it in your root build.gradle at the end of repositories:
allprojects {
	repositories {
		...
		maven { 
			url "https://jitpack.io" 
		}
	}
}
  • Add the dependency:
dependencies {
	 compile 'com.github.BlackBoxVision:mvp-helpers:v0.0.1-kt'
}

Maven

  • Add this line to repositories section in pom.xml:
<repositories>
	<repository>
	   <id>jitpack.io</id>
		 <url>https://jitpack.io</url>
	</repository>
</repositories>
  • Add the dependency:
<dependency>
  <groupId>com.github.BlackBoxVision</groupId>
  <artifactId>mvp-helpers</artifactId>
	<version>v0.0.1-kt</version>
</dependency>

SBT

  • Add it in your build.sbt at the end of resolvers:
  resolvers += "jitpack" at "https://jitpack.io"
  • Add the dependency:
  libraryDependencies += "com.github.BlackBoxVision" % "mvp-helpers" % "v0.0.1-kt"	

##Usage example

The usage is really simple, the concepts behind this library are the following ones:

  • View → The View is an interface that contains methods related to UI interaction, to create you own you should extends the BaseView like in the following example:
public interface DetailsView extends BaseView {

  void onInfoReceived(@NonNull Bundle information);
  
  void onInfoError(@NonNull String errorMessage);
}
  • 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.

When you extend the BaseInteractor class, you get two useful methods runOnBackground and runOnUiThread. Both methods receives a Runnable as param.

  • runOnBackground is a method that executes the runnable you pass to it in an Executor. The executor is an instance generated by Executors class, it provides you with a fixed thread pool executor of 5 theads. Enough to do hard work.

  • runOnUiThread is a method that executes the runnable you pass to it in an Handler. The handler instance is generated with a reference to the Main Looper. In this way, we know that we really comunicate to the correct thread the updates to post, in our case, the UI one.

Check the following example:

//This example uses Java 8 features, I assume the usage of retrolambda
public final class DetailsInteractor extends BaseInteractor {

  public void retrieveDetailsFromService(@NonNull final String id, @NonNull final OnSuccessListener<Bundle> successListener, @NonNull final OnErrorListener<String> errorListener) {
    runOnBackground(() -> {
      //Getting data from somewhere
      Bundle data = ... ;   
      
      runOnUiThread(() -> {
      	if (data != null) {
			successListener.onSuccess(data);	
		} else {
			errorListener.onError("Ups, something went wrong");
		}
      });
    })
  }
}
  • Presenter → The presenter acts as a middle man between the Interactor and the View. When you request something to the presenter, he contacts the interactor object to get what he needs, and then he interacts with the view to make you get what you really need. Continue with the example of a Details:
//I use method references from Java 8 to point the callbacks to interactor, I assume a working project with Retrolambda
public final class DetailsPresenter extends BasePresenter<DetailsView> {
  private DetailsInteractor interactor;
  
  public DetailsPresenter() { 
    interactor = new DetailsInteractor();
  }
  
  public void getInformationFromId(@NonNull String id) {
    if (isViewAttached()) {
      interactor.retrieveDetailsFromService(id, this::onSuccess, this::onError);
    }
  }
  
  private void onSuccess(@NonNull Bundle data) {
    if (isViewAttached()) {
      getView().onInfoReceived(data);
    }
  }
  
  private void onError(@NonNull String errorMessage) {
    if (isViewAttached()) {
      getView().onInfoError(errorMessage);
    }
  }
}

As you see, BasePresenter is a generic class, you have to pass to it the View that you want to use when you inherit from it. BasePresenter provides you with a set of methods to deal with view interfaces, that are the following ones:

  • isViewAttached → This method checks if you have set the view to the presenter, returns to you a boolean value that you should handle in your presenter implementation.

  • detachView → This method 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.

  • attachView → This method adds the view to the presenter, so you can start to handle the cicle of view - presenter - interactor interaction.

  • getView → simple getter, to make your access to the view defined more cleaner.

##Complement with Android

Well, that's the basics behind the library. At this point, you are asking yourself, how do I connect this classes with a Android??. Well, that's pretty simple!

I work a lot with Fragments, they simplify a lot my work flow. I think in them as the View in Android. I let Activity manage Fragments, don't want to charge them, since they have a lot of responsabilities.

To finalize the explanation, check the sample implementation:

public final class DetailsFragment extends BaseFragment<DetailsPresenter> implements DetailsView {
    
    @Override
    public addPresenter() {
      	return new DetailsPresenter();
    }
    
    @LayoutRes
    @Override
    public int getLayout() {
      	return R.layout.fragment_details;
    }
    
    @Override
    void onPresenterCreated(@NonNull DetailsPresenter presenter) {
    	presenter.attachView(this);
    }
    
    @Override
    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        getPresenter().getInformationFromId("ssdWRGD132");
    }
    
    @Override
    void onInfoReceived(@NonNull Bundle information) {
       Toast.makeText(getContext(), information.toString(), Toast.LENGTH_SHORT).show();
    }
    
    @Override
    void onInfoError(@NonNull String errorMessage) {
       Toast.makeText(getContext(), errorMessage, Toast.LENGTH_SHORT).show();
    }
} 

As you see, this Fragment is a generic class that solves some troubles for you, It has the ability to detach view for you in onDestroyView so you don't have to, auto inject views with butter knife, and lifecycle methods simplified.

When you inherit it, you will get the following methods to implement:

  • addPresenter → in this method you have to create you instance of Presenter.

  • getLayout → in this method you have pass the id reference to the layout. This library comes with ButterKnife, to provide efficiency I have implemented onCreateView in BaseFragment where I call ButterKnife.bind method, so you have view binding out of the box! 😄

  • getPresenter → simple getter, to make your access to the presenter more cleaner.

  • onPresenterCreated → In this method you should attach the view to the presenter in order to start working.

##Some notes on ButterKnife

The standard ButterKnife library is included by default. But there is a missing point, you have to add in your app build.gradle file the annotation procesor, if not, @Bind annotations won't work:

dependencies {
  annotationProcessor 'com.jakewharton:butterknife-compiler:8.4.0'
}

##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

###JAVA

  • 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

###KOTLIN

0.0.1

  • Work in progress

##License

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

mvp-helpers's People

Watchers

 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.