
io.taig.android.mosby.delegate.DialogFragmentMvpDelegateImpl Maven / Gradle / Ivy
/*
* Copyright 2015 Hannes Dorfmann.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.taig.android.mosby.delegate;
import android.app.Activity;
import android.app.Fragment;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.util.Log;
import com.hannesdorfmann.mosby3.PresenterManager;
import com.hannesdorfmann.mosby3.mvp.MvpPresenter;
import com.hannesdorfmann.mosby3.mvp.MvpView;
import com.hannesdorfmann.mosby3.mvp.delegate.MvpDelegateCallback;
import java.util.UUID;
/**
* The default implementation of {@link DialogFragmentMvpDelegate}
* Presenter is available (has view that is attached) in {@link #onCreateDialog(Bundle)}} (after
* super.onViewCreated() is called). View will be detached in {@link #onDestroyView()} from presenter,
* and eventually presenter will be destroyed in {@link #onDestroy()}.
*
* @param The type of {@link MvpView}
* @param The type of {@link MvpPresenter}
* @author Hannes Dorfmann
* @see DialogFragmentMvpDelegate
* @since 1.1.0
*/
public class DialogFragmentMvpDelegateImpl>
implements DialogFragmentMvpDelegate {
protected static final String KEY_MOSBY_VIEW_ID = "com.hannesdorfmann.mosby3.fragment.mvp.id";
public static boolean DEBUG = false;
private static final String DEBUG_TAG = "FragmentMvpVSDelegate";
private MvpDelegateCallback delegateCallback;
protected Fragment fragment;
protected final boolean keepPresenterInstanceDuringScreenOrientationChanges;
protected final boolean keepPresenterOnBackstack;
protected String mosbyViewId;
/**
* @param fragment The Fragment
* @param delegateCallback the DelegateCallback
* @param keepPresenterDuringScreenOrientationChange true, if the presenter should be kept during
* screen orientation
* changes. Otherwise, false
* @param keepPresenterOnBackstack true, if the presenter should be kept when the fragment is
* destroyed because it is put on the backstack, Otherwise false
*/
public DialogFragmentMvpDelegateImpl( @NonNull Fragment fragment,
@NonNull MvpDelegateCallback delegateCallback,
boolean keepPresenterDuringScreenOrientationChange, boolean keepPresenterOnBackstack) {
if (delegateCallback == null) {
throw new NullPointerException("MvpDelegateCallback is null!");
}
if (fragment == null) {
throw new NullPointerException("Fragment is null!");
}
if (!keepPresenterDuringScreenOrientationChange && keepPresenterOnBackstack) {
throw new IllegalArgumentException("It is not possible to keep the presenter on backstack, "
+ "but NOT keep presenter through screen orientation changes. Keep presenter on backstack also "
+ "requires keep presenter through screen orientation changes to be enabled");
}
this.fragment = fragment;
this.delegateCallback = delegateCallback;
this.keepPresenterInstanceDuringScreenOrientationChanges =
keepPresenterDuringScreenOrientationChange;
this.keepPresenterOnBackstack = keepPresenterOnBackstack;
}
/**
* Generates the unique (mosby internal) view id and calls {@link
* MvpDelegateCallback#createPresenter()}
* to create a new presenter instance
*
* @return The new created presenter instance
*/
private P createViewIdAndCreatePresenter() {
P presenter = delegateCallback.createPresenter();
if (presenter == null) {
throw new NullPointerException(
"Presenter returned from createPresenter() is null. Activity is " + getActivity());
}
if (keepPresenterInstanceDuringScreenOrientationChanges) {
mosbyViewId = UUID.randomUUID().toString();
PresenterManager.putPresenter(getActivity(), mosbyViewId, presenter);
}
return presenter;
}
@Override
public void onCreateDialog( @Nullable Bundle savedInstanceState ) {
}
@Override
public void onCreateView() {
P presenter = getPresenter();
presenter.attachView(getMvpView());
if (DEBUG) {
Log.d(DEBUG_TAG, "View" + getMvpView() + " attached to Presenter " + presenter);
}
}
@NonNull
private Activity getActivity() {
Activity activity = fragment.getActivity();
if (activity == null) {
throw new NullPointerException(
"Activity returned by Fragment.getActivity() is null. Fragment is " + fragment);
}
return activity;
}
private P getPresenter() {
P presenter = delegateCallback.getPresenter();
if (presenter == null) {
throw new NullPointerException("Presenter returned from getPresenter() is null");
}
return presenter;
}
private V getMvpView() {
V view = delegateCallback.getMvpView();
if (view == null) {
throw new NullPointerException("View returned from getMvpView() is null");
}
return view;
}
static boolean retainPresenterInstance( Activity activity, Fragment fragment,
boolean keepPresenterInstanceDuringScreenOrientationChanges,
boolean keepPresenterOnBackstack) {
if (activity.isChangingConfigurations()) {
return keepPresenterInstanceDuringScreenOrientationChanges;
}
if (activity.isFinishing()) {
return false;
}
if (keepPresenterOnBackstack && BackstackAccessor.isFragmentOnBackStack(fragment)) {
return true;
}
return !fragment.isRemoving();
}
@Override
public void onDestroyView() {
getPresenter().detachView();
if (DEBUG) {
Log.d(DEBUG_TAG, "detached MvpView from Presenter. MvpView "
+ delegateCallback.getMvpView()
+ " Presenter: "
+ getPresenter());
}
}
@Override
public void onPause() {
}
@Override
public void onResume() {
}
@Override
public void onStart() {
}
@Override
public void onStop() {
}
@Override
public void onActivityCreated( Bundle savedInstanceState) {
}
@Override
public void onAttach( Activity activity) {
}
@Override
public void onDetach() {
}
@Override
public void onSaveInstanceState( Bundle outState) {
if ((keepPresenterInstanceDuringScreenOrientationChanges || keepPresenterOnBackstack)
&& outState != null) {
outState.putString(KEY_MOSBY_VIEW_ID, mosbyViewId);
if (DEBUG) {
Log.d(DEBUG_TAG, "Saving MosbyViewId into Bundle. ViewId: " + mosbyViewId);
}
}
}
@Override
public void onCreate( Bundle bundle) {
P presenter = null;
if (bundle != null && keepPresenterInstanceDuringScreenOrientationChanges) {
mosbyViewId = bundle.getString(KEY_MOSBY_VIEW_ID);
if (DEBUG) {
Log.d(DEBUG_TAG,
"MosbyView ID = " + mosbyViewId + " for MvpView: " + delegateCallback.getMvpView());
}
if (mosbyViewId != null
&& (presenter = PresenterManager.getPresenter(getActivity(), mosbyViewId)) != null) {
//
// Presenter restored from cache
//
if (DEBUG) {
Log.d(DEBUG_TAG,
"Reused presenter " + presenter + " for view " + delegateCallback.getMvpView());
}
} else {
//
// No presenter found in cache, most likely caused by process death
//
presenter = createViewIdAndCreatePresenter();
if (DEBUG) {
Log.d(DEBUG_TAG, "No presenter found although view Id was here: "
+ mosbyViewId
+ ". Most likely this was caused by a process death. New Presenter created"
+ presenter
+ " for view "
+ getMvpView());
}
}
} else {
//
// Activity starting first time, so create a new presenter
//
presenter = createViewIdAndCreatePresenter();
if (DEBUG) {
Log.d(DEBUG_TAG, "New presenter " + presenter + " for view " + getMvpView());
}
}
if (presenter == null) {
throw new IllegalStateException(
"Oops, Presenter is null. This seems to be a Mosby internal bug. Please report this issue here: https://github.com/sockeqwe/mosby/issues");
}
delegateCallback.setPresenter(presenter);
}
@Override
public void onDestroy() {
Activity activity = getActivity();
boolean retainPresenterInstance = retainPresenterInstance(activity, fragment,
keepPresenterInstanceDuringScreenOrientationChanges, keepPresenterOnBackstack);
P presenter = getPresenter();
if (!retainPresenterInstance) {
presenter.destroy();
if (DEBUG) {
Log.d(DEBUG_TAG, "Presenter destroyed. MvpView "
+ delegateCallback.getMvpView()
+ " Presenter: "
+ presenter);
}
}
if (!retainPresenterInstance && mosbyViewId != null) {
// mosbyViewId is null if keepPresenterInstanceDuringScreenOrientationChanges == false
PresenterManager.remove(activity, mosbyViewId);
}
}
}