/* * Copyright 2016 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 com.hannesdorfmann.mosby3.mvi; import android.app.Activity; import android.content.Context; import android.content.res.Configuration; import android.os.Bundle; import android.support.annotation.CallSuper; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.support.v4.app.Fragment; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import com.hannesdorfmann.mosby3.ActivityMviDelegate; import com.hannesdorfmann.mosby3.FragmentMviDelegate; import com.hannesdorfmann.mosby3.FragmentMviDelegateImpl; import com.hannesdorfmann.mosby3.MviDelegateCallback; import com.hannesdorfmann.mosby3.mvp.MvpPresenter; import com.hannesdorfmann.mosby3.mvp.MvpView; /** * <p> * This abstract class can be used to extend from to implement an Model-View-Intent pattern with * this activity as View and a {@link MviPresenter} to coordinate the View and the underlying * model (business logic) * </p> * * <p> * Per default {@link FragmentMviDelegateImpl} is used with the following lifecycle: * The View is attached to the Presenter in {@link Fragment#onViewCreated(View, Bundle)}. * So you better instantiate all your UI widgets before that lifecycle callback (typically in * {@link * Fragment#onCreateView(LayoutInflater, ViewGroup, Bundle)}. The View is detached from Presenter in * {@link Fragment#onDestroyView()} * </p> * * @author Hannes Dorfmann * @since 3.0.0 */ public abstract class MviFragment<V extends MvpView, P extends MviPresenter<V, ?>> extends Fragment implements MvpView, MviDelegateCallback<V, P> { private boolean isRestoringViewState = false; protected FragmentMviDelegate<V, P> mvpDelegate; @CallSuper @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); getMvpDelegate().onCreate(savedInstanceState); } @CallSuper @Override public void onDestroy() { super.onDestroy(); getMvpDelegate().onDestroy(); } @CallSuper @Override public void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); getMvpDelegate().onSaveInstanceState(outState); } @CallSuper @Override public void onPause() { super.onPause(); getMvpDelegate().onPause(); } @CallSuper @Override public void onResume() { super.onResume(); getMvpDelegate().onResume(); } @CallSuper @Override public void onStart() { super.onStart(); getMvpDelegate().onStart(); } @CallSuper @Override public void onStop() { super.onStop(); getMvpDelegate().onStop(); } @CallSuper @Override public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); getMvpDelegate().onViewCreated(view, savedInstanceState); } @CallSuper @Override public void onDestroyView() { super.onDestroyView(); getMvpDelegate().onDestroyView(); } @CallSuper @Override public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); getMvpDelegate().onActivityCreated(savedInstanceState); } @CallSuper @Override public void onAttach(Activity activity) { super.onAttach(activity); getMvpDelegate().onAttach(activity); } @Override public void onAttach(Context context) { super.onAttach(context); getMvpDelegate().onAttach(context); } @CallSuper @Override public void onDetach() { super.onDetach(); getMvpDelegate().onDetach(); } @CallSuper @Override public void onAttachFragment(Fragment childFragment) { super.onAttachFragment(childFragment); getMvpDelegate().onAttachFragment(childFragment); } @CallSuper @Override public void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); getMvpDelegate().onConfigurationChanged(newConfig); } /** * Instantiate a presenter instance * * @return The {@link MvpPresenter} for this viewState */ @NonNull public abstract P createPresenter(); /** * Get the mvp delegate. This is internally used for creating presenter, attaching and detaching * viewState from presenter. * * <p><b>Please note that only one instance of mvp delegate should be used per Activity * instance</b>. * </p> * * <p> * Only override this method if you really know what you are doing. * </p> * * @return {@link ActivityMviDelegate} */ @NonNull public FragmentMviDelegate<V, P> getMvpDelegate() { if (mvpDelegate == null) { mvpDelegate = new FragmentMviDelegateImpl<V, P>(this, this); } return mvpDelegate; } @NonNull @Override public V getMvpView() { try { return (V) this; } catch (ClassCastException e) { String msg = "Couldn't cast the View to the corresponding View interface. Most likely you forgot to add \"Activity implements YourMvpViewInterface\".\""; Log.e(this.toString(), msg); throw new RuntimeException(msg, e); } } @Override public void setRestoringViewState(boolean restoringViewState) { this.isRestoringViewState = restoringViewState; } protected boolean isRestoringViewState() { return isRestoringViewState; } }