package nucleus.view;
import android.os.Bundle;
import android.os.Parcelable;
import android.support.annotation.Nullable;
import nucleus.factory.PresenterFactory;
import nucleus.factory.PresenterStorage;
import nucleus.presenter.Presenter;
/**
* This class adopts a View lifecycle to the Presenter`s lifecycle.
*
* @param <P> a type of the presenter.
*/
public final class PresenterLifecycleDelegate<P extends Presenter> {
private static final String PRESENTER_KEY = "presenter";
private static final String PRESENTER_ID_KEY = "presenter_id";
@Nullable
private PresenterFactory<P> presenterFactory;
@Nullable
private P presenter;
@Nullable
private Bundle bundle;
private boolean presenterHasView;
public PresenterLifecycleDelegate(@Nullable PresenterFactory<P> presenterFactory) {
this.presenterFactory = presenterFactory;
}
/**
* {@link ViewWithPresenter#getPresenterFactory()}
*/
@Nullable
public PresenterFactory<P> getPresenterFactory() {
return presenterFactory;
}
/**
* {@link ViewWithPresenter#setPresenterFactory(PresenterFactory)}
*/
public void setPresenterFactory(@Nullable PresenterFactory<P> presenterFactory) {
if (presenter != null)
throw new IllegalArgumentException("setPresenterFactory() should be called before onResume()");
this.presenterFactory = presenterFactory;
}
/**
* {@link ViewWithPresenter#getPresenter()}
*/
public P getPresenter() {
if (presenterFactory != null) {
if (presenter == null && bundle != null)
presenter = PresenterStorage.INSTANCE.getPresenter(bundle.getString(PRESENTER_ID_KEY));
if (presenter == null) {
presenter = presenterFactory.createPresenter();
PresenterStorage.INSTANCE.add(presenter);
presenter.create(bundle == null ? null : bundle.getBundle(PRESENTER_KEY));
}
bundle = null;
}
return presenter;
}
/**
* {@link android.app.Activity#onSaveInstanceState(Bundle)}, {@link android.app.Fragment#onSaveInstanceState(Bundle)}, {@link android.view.View#onSaveInstanceState()}.
*/
public Bundle onSaveInstanceState() {
Bundle bundle = new Bundle();
getPresenter();
if (presenter != null) {
Bundle presenterBundle = new Bundle();
presenter.save(presenterBundle);
bundle.putBundle(PRESENTER_KEY, presenterBundle);
bundle.putString(PRESENTER_ID_KEY, PresenterStorage.INSTANCE.getId(presenter));
}
return bundle;
}
/**
* {@link android.app.Activity#onCreate(Bundle)}, {@link android.app.Fragment#onCreate(Bundle)}, {@link android.view.View#onRestoreInstanceState(Parcelable)}.
*/
public void onRestoreInstanceState(Bundle presenterState) {
if (presenter != null)
throw new IllegalArgumentException("onRestoreInstanceState() should be called before onResume()");
this.bundle = ParcelFn.unmarshall(ParcelFn.marshall(presenterState));
}
/**
* {@link android.app.Activity#onResume()},
* {@link android.app.Fragment#onResume()},
* {@link android.view.View#onAttachedToWindow()}
*/
public void onResume(Object view) {
getPresenter();
if (presenter != null && !presenterHasView) {
//noinspection unchecked
presenter.takeView(view);
presenterHasView = true;
}
}
/**
* {@link android.app.Activity#onDestroy()},
* {@link android.app.Fragment#onDestroyView()},
* {@link android.view.View#onDetachedFromWindow()}
*/
public void onDropView() {
if (presenter != null && presenterHasView) {
presenter.dropView();
presenterHasView = false;
}
}
/**
* {@link android.app.Activity#onDestroy()},
* {@link android.app.Fragment#onDestroy()},
* {@link android.view.View#onDetachedFromWindow()}
*/
public void onDestroy(boolean isFinal) {
if (presenter != null && isFinal) {
presenter.destroy();
presenter = null;
}
}
}