/* * Copyright (C) 2015 OpenSilk Productions LLC * * 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 org.opensilk.common.ui.mortarfragment; import android.app.Dialog; import android.content.Context; import android.os.Bundle; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.support.v4.app.DialogFragment; import android.support.v4.app.Fragment; import android.support.v7.app.AppCompatDialog; import android.support.v7.app.AppCompatDialogFragment; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import org.opensilk.common.ui.mortar.LayoutCreator; import org.opensilk.common.ui.mortar.Screen; import org.opensilk.common.ui.mortar.ScreenScoper; import mortar.MortarScope; import timber.log.Timber; /** * Created by drew on 3/16/15. */ public abstract class MortarDialogFragment extends AppCompatDialogFragment { private static final boolean DEBUG_LIFECYCLE = false; private MortarScope mScope; private Screen mScreen; protected abstract Screen newScreen(); protected boolean shouldRetainScope() { return true; } @Override public void onCreate(Bundle savedInstanceState) { if (DEBUG_LIFECYCLE) Timber.v("->onCreate %s", getScopeName()); super.onCreate(savedInstanceState); mScope = findOrMakeScope(); setRetainInstance(shouldRetainScope()); if (DEBUG_LIFECYCLE) Timber.v("<-onCreate %s", getScopeName()); } @NonNull @Override public Dialog onCreateDialog(Bundle savedInstanceState) { return new AppCompatDialog(mScope.createContext(getActivity()), getTheme()); } @Override public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { LayoutCreator layoutCreator = LayoutCreator.getService(getActivity()); //Watch out, inflater here is assumed to be from the dialogs context return inflater.inflate(layoutCreator.getLayout(getScreen()), container, false); } @Override public void onActivityCreated(@Nullable Bundle savedInstanceState) { if (DEBUG_LIFECYCLE) Timber.v("->onActivityCreated %s", getScopeName()); super.onActivityCreated(savedInstanceState); if (DEBUG_LIFECYCLE) Timber.v("<-onActivityCreated %s", getScopeName()); } @Override public void onDestroyView() { if (shouldRetainScope() && getDialog() != null) { getDialog().setDismissMessage(null); } super.onDestroyView(); } @Override public void onDestroy() { if (DEBUG_LIFECYCLE) Timber.v("->onDestroy %s", getScopeName()); super.onDestroy(); if (mScope != null) { Timber.d("Destroying fragment scope %s", getScopeName()); mScope.destroy(); mScope = null; } if (DEBUG_LIFECYCLE) Timber.v("<-onDestroy %s", getScopeName()); } private MortarScope findOrMakeScope() { MortarScope scope = MortarScope.findChild(getActivity(), getScopeName()); if (scope != null) { Timber.d("Reusing fragment scope %s", getScopeName()); } if (scope == null) { ScreenScoper scoper = ScreenScoper.getService(getActivity()); scope = scoper.getScreenScope(getActivity(), getScreen()); Timber.d("Created new fragment scope %s", getScopeName()); } return scope; } //Enforce using screen name as scope name, this is also used to tag the fragment public final String getScopeName() { return getScreen().getName(); } @NonNull public final MortarScope getScope() { if (mScope == null) { throw new IllegalStateException("Can't call getScope() before onCreate()"); } return mScope; } @NonNull public final Screen getScreen() { if (mScreen == null) { mScreen = newScreen(); } return mScreen; } public static <T extends MortarDialogFragment> T factory(Context context, String name, Bundle args) { return (T) Fragment.instantiate(context, name, args); } }