♻️Helper classes to build Android Apps through MVP pattern in a faster way
Helper classes to build Android Apps through MVP pattern in a faster way
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!
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:
allprojects {
repositories {
...
maven {
url "https://jitpack.io"
}
}
}
Add the dependency:
dependencies {
compile 'com.github.BlackBoxVision
v0.2.0'
}
Maven
<repositories>
<repository>
<id>jitpack.io</id>
<url>https://jitpack.io</url>
</repository>
</repositories>
<dependency>
<groupId>com.github.BlackBoxVision</groupId>
<artifactId>mvp-helpers</artifactId>
<version>v0.2.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.2.0"
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.
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.
public interface DetailsView extends BaseView {
void onInfoReceived(@NonNull Bundle information);
void onInfoError(@NonNull String errorMessage);
}
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:
//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
final Bundle data = MockUtils.getMockedData(id);
runOnUiThread(() -> {
if (data != null) {
successListener.onSuccess(data);
} else {
errorListener.onError("Ups, something went wrong");
}
});
});
}
}
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:
//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;
@Override
protected void onViewAttached(@NonNull DetailsView view) {
interactor = new DetailsInteractor();
}
@Override
protected void onViewDetached() {
interactor = null;
}
public void findRequiredInformation(@NonNull String id) {
if (isViewAttached()) {
interactor.retrieveDetailsFromService(id, this::onSuccess, this::onError);
}
}
private void onSuccess(@NonNull Bundle information) {
if (isViewAttached()) {
getView().onInfoReceived(information);
}
}
private void onError(@NonNull String errorMessage) {
if (isViewAttached()) {
getView().onInfoError(errorMessage);
}
}
}
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.
class DetailsPresenterFactory implements PresenterFactory<DetailsPresenter> {
@Override
public DetailsPresenter create() {
return new DetailsPresenter();
}
}
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:
public final class DetailsFragment extends BaseFragment<DetailsPresenter, DetailsView> implements DetailsView {
@Override
protected DetailsPresenterFactory createPresenterFactory() {
return new DetailsPresenterFactory();
}
@LayoutRes
@Override
protected int getLayout() {
return R.layout.fragment_details;
}
@Override
protected void onPresenterCreated(@NonNull DetailsPresenter presenter) {
//Do something when presenter it's created
getPresenter().getInformationFromId("ssdWRGD132");
}
@Override
protected void onPresenterDestroyed() {
//Do something when presenter is removed, this method is called in onDestroy
}
@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();
}
}
From version 0.2.0 of this library, I have decided to remove butterKnife, in order to not force any dev to use butterKnife.
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.
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!
0.2.0
0.1.0
Distributed under the MIT license. See LICENSE for more information.