package in.mvpstarter.sample.ui.base;
import rx.Observable;
import rx.Single;
import rx.Subscription;
import rx.subscriptions.CompositeSubscription;
/**
* Base class that implements the Presenter interface and provides a base implementation for
* attachView() and detachView(). It also handles keeping a reference to the mvpView that
* can be accessed from the children classes by calling getMvpView().
*/
public class BasePresenter<T extends MvpView> implements Presenter<T> {
private T mMvpView;
private final CompositeSubscription mCompositeSubscription = new CompositeSubscription();
@Override
public void attachView(T mvpView) {
mMvpView = mvpView;
}
@Override
public void detachView() {
mMvpView = null;
if (!mCompositeSubscription.isUnsubscribed()) {
mCompositeSubscription.clear();
}
}
public boolean isViewAttached() {
return mMvpView != null;
}
public T getMvpView() {
return mMvpView;
}
public void checkViewAttached() {
if (!isViewAttached()) throw new MvpViewNotAttachedException();
}
public void addSubscription(Subscription subs) {
mCompositeSubscription.add(subs);
}
private static class MvpViewNotAttachedException extends RuntimeException {
MvpViewNotAttachedException() {
super("Please call Presenter.attachView(MvpView) before" +
" requesting data to the Presenter");
}
}
/**
* Encapsulate the result of an rx Observable.
* This model is meant to be used by the children presenters to easily keep a reference
* to the latest loaded result so that it can be easily emitted again when on configuration
* changes.
*/
protected static class DataResult<T> {
private T mData;
private Throwable mError;
public DataResult(T data) {
mData = data;
}
public DataResult(Throwable error) {
mError = error;
}
public Single<T> toSingle() {
if (mError != null) {
return Single.error(mError);
}
return Single.just(mData);
}
public Observable<T> toObservable() {
if (mError != null) {
return Observable.error(mError);
}
return Observable.just(mData);
}
}
}