How it works - mandriana/android-mvp-core GitHub Wiki

This section goal is to present the library architecture behind the fact that it is MVP.

MVP Core

The core library contains minimal requirements to use the MVP architecture.

The implementation relies on retaining the presenters in a PresenterCache to keep them alive across orientation change. Presenters can be manipulated using the PresenterController class. This controller can be used to attach / detach the view to the presenter, retrieve a presenter from the cache (see PresenterController)

Presenter

A presenter should extends the abstract class Presenter. A presenter has a lifecycle and can be notified of the times the view is attached to the presenter or detached. Available methods for override are :

  • onCreate : called when the presenter is created (instantiated)
  • onCreateThenAttached : called the first time the view is attached to the presenter
  • onViewAttached : called when the view is attached
  • onViewDetached : called when the view is detached
  • onDestroy : called when the presenter is destroyed

A presenter can access the view through the method getView()which is annotated @Nullable. This method does need to be checked against nullto access view members or properties.

RxPresenter

The RxPresenter is a base presenter which provides features to perform task using RxJava with many benefits :

  • no need to use the getView() to dispatch results to the view, meaning no null check
  • ability to start observables and cancel them
  • ability to retrieve observables result even after an orientation change or a pause and resume

The full method to start observables is :

public <Result> void start(@NonNull final String tag,
                           @NonNull Observable<Result> observable,
                           boolean withDefaultSchedulers,
                           @Nullable final OnNext<V, Result> onNext,
                           @Nullable final OnError<V> onError,
                           @Nullable final OnCompleted<V> onCompleted)

The parameters of this methods are :

  • tag : a tag to identify a task which will be used in case of cancellation
  • observable : the observable to execute
  • withDefaultSchedulers : a boolean to set to use default schedulers which are observable.observeOn(AndroidSchedulers.mainThread()).subscribeOn(Schedulers.io())
  • onNext : on next action with two parameters which are typed on the view type V and result type Result
  • onError : on error callback with two parameters which are the view and the throwable
  • onCompleted : on completed callback with the view as parameter

Shortcuts of this method are also available (RxPresenter)) if you only need the OnNext and OnError callbacks ...

public class MainPresenter extends RxPresenter<MainView> {
    
    private static final String TASK_DO_STUFF = "doStuff";
    
    public void doStuff() {
        start(TASK_DO_STUFF, Observable.just(1,2,3,4),
                new OnNext<MainView, Integer>() {
                    @Override
                    public void call(@NonNull MainView mainView, @NonNull Integer i) {
                        mainView.onNextItem(i);
                    }
                },
                new OnError<MainView>() {
                    @Override
                    public void call(@NonNull MainView mainView, @NonNull Throwable throwable) {
                        mainView.onTaskFailed();
                    }
                },
                new OnCompleted<MainView>() {
                    @Override
                    public void call(@NonNull MainView mainView) {
                        mainView.onTaskCompleted();
                    }
                });
    }
}

As you can see the view is available inside each callback as a parameter, the getView() method is not used at all. This ensure onNextItem(i), onTaskFailed() and onTaskCompleted() are called with a non null view i.e the view is attached.

View attached and detached

If you only use the core library, you are responsible for the attach/detach process of your view and presenter.

If you use the mvp-base-view library you can access to a BasePresenterActivity and a BasePresenterFragment. These base classes perform all the work for you to tie the view to the presenter.

Mvp Base Views

Since to 1.1.0 (with dagger)

Constructor injection is now easier with dagger.

There is no need anymore of the functions injectActivity(), injectFragment() and instantiatePresenter() in the BasePresenterActivity nor BasePresenterFragment. Instead you can just :

@PresenterClass(MainPresenter.class)
public class MainActivity extends BasePresenterActivity<MainPresenter> implements MainView {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        MVPApplication.mAppComponent.inject(this);
        super.onCreate(savedInstanceState);

        ...
    }
}

Prior to 1.1.0 (with or without dagger)

This library enhance the core library be providing two ready to use base classes :

  • BasePresenterActivity
  • BasePresenterFragment

The abstract methods you must override are :

@NonNull protected abstract P instantiatePresenter();

where you need to instantiate your presenter. Keep in mind that a presenter is instantiated only the first time it is accessed using the getPresenter() method. If you do not call this method, no instantiation will be performed, avoiding allocating memory for unused presenter.

And :

@NonNull protected abstract PresenterCache getPresenterCache();

where you must return the PresenterCache instance.

View attached and detached

As mentioned previously the view will be attached to the presenter in onResume() and detached in onPause. This choice was made to manipulate the view when it is visible to the user. In a next version a configurator will be available to attach view in onStart or onResume and detaching it in the corresponding method.

Presenter destruction

When a presenter is destroyed using the destroyPresenter() method, it is removed from the presenter cache.

BasePresenterActivity

If you use this class, the presenter will be destroyed automatically when onPause is called with isFinishing() returning true or when calling finish(). You can manually fire a presenter destruction by calling destroyPresenter().

BasePresenterFragment

With fragments the destruction depends on the call of onPause() with getActivity().isChangingConfigurations() returning false. Because fragments lifecycle can be more complex (using view pager for instance), you may have to deal with the presenter destruction yourself when needed using the method destroyPresenter().

⚠️ **GitHub.com Fallback** ⚠️