package nucleus.view; import android.app.Activity; import android.content.Context; import android.content.ContextWrapper; import android.os.Bundle; import android.os.Parcelable; import android.util.AttributeSet; import android.widget.FrameLayout; import nucleus.factory.PresenterFactory; import nucleus.factory.ReflectionPresenterFactory; import nucleus.presenter.Presenter; /** * This view is an example of how a view should control it's presenter. * You can inherit from this class or copy/paste this class's code to * create your own view implementation. * * @param <P> a type of presenter to return with {@link #getPresenter}. */ public class NucleusLayout<P extends Presenter> extends FrameLayout implements ViewWithPresenter<P> { private static final String PARENT_STATE_KEY = "parent_state"; private static final String PRESENTER_STATE_KEY = "presenter_state"; private PresenterLifecycleDelegate<P> presenterDelegate = new PresenterLifecycleDelegate<>(ReflectionPresenterFactory.<P>fromViewClass(getClass())); public NucleusLayout(Context context) { super(context); } public NucleusLayout(Context context, AttributeSet attrs) { super(context, attrs); } public NucleusLayout(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } /** * Returns a current presenter factory. */ public PresenterFactory<P> getPresenterFactory() { return presenterDelegate.getPresenterFactory(); } /** * Sets a presenter factory. * Call this method before onCreate/onFinishInflate to override default {@link ReflectionPresenterFactory} presenter factory. * Use this method for presenter dependency injection. */ @Override public void setPresenterFactory(PresenterFactory<P> presenterFactory) { presenterDelegate.setPresenterFactory(presenterFactory); } /** * Returns a current attached presenter. * This method is guaranteed to return a non-null value between * onResume/onPause and onAttachedToWindow/onDetachedFromWindow calls * if the presenter factory returns a non-null value. * * @return a currently attached presenter or null. */ public P getPresenter() { return presenterDelegate.getPresenter(); } /** * Returns the unwrapped activity of the view or throws an exception. * * @return an unwrapped activity */ public Activity getActivity() { Context context = getContext(); while (!(context instanceof Activity) && context instanceof ContextWrapper) context = ((ContextWrapper) context).getBaseContext(); if (!(context instanceof Activity)) throw new IllegalStateException("Expected an activity context, got " + context.getClass().getSimpleName()); return (Activity) context; } @Override protected Parcelable onSaveInstanceState() { Bundle bundle = new Bundle(); bundle.putBundle(PRESENTER_STATE_KEY, presenterDelegate.onSaveInstanceState()); bundle.putParcelable(PARENT_STATE_KEY, super.onSaveInstanceState()); return bundle; } @Override protected void onRestoreInstanceState(Parcelable state) { Bundle bundle = (Bundle) state; super.onRestoreInstanceState(bundle.getParcelable(PARENT_STATE_KEY)); presenterDelegate.onRestoreInstanceState(bundle.getBundle(PRESENTER_STATE_KEY)); } @Override protected void onAttachedToWindow() { super.onAttachedToWindow(); if (!isInEditMode()) presenterDelegate.onResume(this); } @Override protected void onDetachedFromWindow() { super.onDetachedFromWindow(); presenterDelegate.onDropView(); presenterDelegate.onDestroy(!getActivity().isChangingConfigurations()); } }