Java tutorial
/* * ================================================================================================= * Copyright (C) 2015 Martin Albedinsky * ================================================================================================= * Licensed under the Apache License, Version 2.0 or later (further "License" only). * ------------------------------------------------------------------------------------------------- * You may use this file only in compliance with the License. More details and copy of this License * you may obtain at * * http://www.apache.org/licenses/LICENSE-2.0 * * You can redistribute, modify or publish any part of the code written within this file but as it * is described in the License, the software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES or CONDITIONS OF ANY KIND. * * See the License for the specific language governing permissions and limitations under the License. * ================================================================================================= */ package com.albedinsky.android.support.universi; import android.app.Activity; import android.content.Context; import android.os.Bundle; import android.support.annotation.IntRange; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentActivity; import android.support.v4.app.FragmentManager; import android.support.v4.app.LoaderManager; import android.support.v4.content.Loader; import com.albedinsky.android.support.dialog.manage.DialogController; import com.albedinsky.android.support.fragment.manage.FragmentController; import com.albedinsky.android.ui.transition.BaseNavigationalTransition; /** * An {@link UniversiContextDelegate} implementation that can be used within context of {@link Activity}. * Activity delegate has additional support for {@link Fragment Fragments} management via {@link FragmentController}. * Fragment controller can be accessed via {@link #getFragmentController()} and custom controller can * be specified via {@link #setFragmentController(FragmentController)}. Fragment factory that provides * fragments to be displayed in a context of a specific UniversiActivity can be specified via * {@link #setFragmentFactory(FragmentController.FragmentFactory)}. * <p> * Navigational transition that can be specified via {@link #setNavigationalTransition(BaseNavigationalTransition)} * can be used to finish the associated activity. * * @author Martin Albedinsky * @see UniversiFragmentDelegate */ final class UniversiActivityDelegate extends UniversiContextDelegate { /** * Interface =================================================================================== */ /** * Constants =================================================================================== */ /** * Log TAG. */ // private static final String TAG = "UniversiActivityDelegate"; /** * Static members ============================================================================== */ /** * Members ===================================================================================== */ /** * Controller that is used to show and hide fragments within the associated activity context. */ private FragmentController mFragmentController; /** * Factory providing fragment instances for the {@link #mFragmentController}. */ private FragmentController.FragmentFactory mFragmentFactory; /** * Navigational transition that can be used to finish the associated activity context. */ private BaseNavigationalTransition mNavigationalTransition; /** * Constructors ================================================================================ */ /** * Creates a new instance of UniversiActivityDelegate for the given activity <var>context</var>. * * @see UniversiContextDelegate#UniversiContextDelegate(Context) */ UniversiActivityDelegate(@NonNull FragmentActivity context) { super(context); } /** * Methods ===================================================================================== */ /** * Starts a loader with the specified <var>id</var>. If there was already started loader with the * same id before, such a loader will be <b>re-started</b>, otherwise new loader will be <b>initialized</b>. * * @param id Id of the desired loader to start. * @param params Params for loader. * @param callbacks Callbacks for loader. * @return Initialized or re-started loader instance or {@code null} if the specified <var>callbacks</var> * do not create loader for the specified <var>id</var>. * @see #initLoader(int, android.os.Bundle, android.support.v4.app.LoaderManager.LoaderCallbacks) * @see #restartLoader(int, android.os.Bundle, android.support.v4.app.LoaderManager.LoaderCallbacks) * @see #destroyLoader(int) */ @Nullable public <D> Loader<D> startLoader(@IntRange(from = 0) int id, @Nullable Bundle params, @NonNull LoaderManager.LoaderCallbacks<D> callbacks) { final LoaderManager manager = ((FragmentActivity) mContext).getSupportLoaderManager(); if (manager.getLoader(id) == null) return initLoader(id, params, callbacks); else return restartLoader(id, params, callbacks); } /** * Initializes a loader with the specified <var>id</var> for the given <var>callbacks</var>. * * @param id Id of the desired loader to init. * @param params Params for loader. * @param callbacks Callbacks for loader. * @return Initialized loader instance or {@code null} if the specified <var>callbacks</var> do * not create loader for the specified <var>id</var>. * @see #startLoader(int, android.os.Bundle, android.support.v4.app.LoaderManager.LoaderCallbacks) * @see #restartLoader(int, android.os.Bundle, android.support.v4.app.LoaderManager.LoaderCallbacks) * @see #destroyLoader(int) * @see LoaderManager#initLoader(int, Bundle, LoaderManager.LoaderCallbacks) */ @Nullable public <D> Loader<D> initLoader(@IntRange(from = 0) int id, @Nullable Bundle params, @NonNull LoaderManager.LoaderCallbacks<D> callbacks) { return ((FragmentActivity) mContext).getSupportLoaderManager().initLoader(id, params, callbacks); } /** * Re-starts a loader with the specified <var>id</var> for the given <var>callbacks</var>. * * @param id Id of the desired loader to re-start. * @param params Params for loader. * @param callbacks Callbacks for loader. * @return Re-started loader instance or {@code null} if the specified <var>callbacks</var> do * not create loader for the specified <var>id</var>. * @see #startLoader(int, android.os.Bundle, android.support.v4.app.LoaderManager.LoaderCallbacks) * @see #initLoader(int, android.os.Bundle, android.support.v4.app.LoaderManager.LoaderCallbacks) * @see #destroyLoader(int) * @see LoaderManager#restartLoader(int, Bundle, LoaderManager.LoaderCallbacks) */ @Nullable public <D> Loader<D> restartLoader(@IntRange(from = 0) int id, @Nullable Bundle params, @NonNull LoaderManager.LoaderCallbacks<D> callbacks) { return ((FragmentActivity) mContext).getSupportLoaderManager().restartLoader(id, params, callbacks); } /** * Destroys a loader with the specified <var>id</var>. * * @param id Id of the desired loader to destroy. * @see #initLoader(int, Bundle, LoaderManager.LoaderCallbacks) * @see #restartLoader(int, Bundle, LoaderManager.LoaderCallbacks) * @see LoaderManager#destroyLoader(int) */ public void destroyLoader(@IntRange(from = 0) int id) { ((FragmentActivity) mContext).getSupportLoaderManager().destroyLoader(id); } /** * Sets a navigational transition that can be used to finish associated activity via * {@link #finishWithNavigationalTransition()} * * @param transition The desired transition. Can be {@code null} to clear the current one. * @see #getNavigationalTransition() */ public void setNavigationalTransition(@Nullable BaseNavigationalTransition transition) { this.mNavigationalTransition = transition; } /** * Returns the navigational transition used to finish associated activity via * {@link #finishWithNavigationalTransition()}. * * @return Attached navigational transition or {@code null} if no transition has been specified. * @see #setNavigationalTransition(BaseNavigationalTransition) */ @Nullable public BaseNavigationalTransition getNavigationalTransition() { return mNavigationalTransition; } /** * Finishes the associated activity with navigational transition specified via * {@link #setNavigationalTransition(BaseNavigationalTransition)} (if any). * * @return {@code True} if transition has been started, {@code false} otherwise. */ public boolean finishWithNavigationalTransition() { if (mNavigationalTransition != null) { mNavigationalTransition.finish((Activity) mContext); return true; } return false; } /** * Sets a controller used to manage (show/hide) fragments in context of the associated activity. * * @param controller The desired controller. Can be {@code null} to use the default one. * @see #getFragmentController() * @see #setFragmentFactory(FragmentController.FragmentFactory) */ public void setFragmentController(@Nullable FragmentController controller) { this.mFragmentController = controller; if (mFragmentFactory != null) { this.ensureFragmentController(); mFragmentController.setFragmentFactory(mFragmentFactory); } } /** * Returns the default controller or the one specified via {@link #setFragmentController(FragmentController)} * that is used to manage fragments of the associated activity. * * @return Fragment controller instance ready to show/hide fragment instances. */ @NonNull public FragmentController getFragmentController() { this.ensureFragmentController(); return mFragmentController; } /** * Sets a factory that provides fragment instances for fragment controller of this delegate. * * @param factory The desired factory. Can be {@code null} to clear the current one. * @see #setFragmentController(FragmentController) * @see #getFragmentController() * @see #getFragmentFactory() */ public void setFragmentFactory(@Nullable FragmentController.FragmentFactory factory) { this.mFragmentFactory = factory; this.ensureFragmentController(); mFragmentController.setFragmentFactory(factory); } /** * Returns the factory providing fragment instances for fragment controller of this delegate. * * @return Instance of fragment factory or {@code null} if no factory has been specified. * @see #setFragmentFactory(FragmentController.FragmentFactory) */ @Nullable public FragmentController.FragmentFactory getFragmentFactory() { return mFragmentFactory; } /** * Ensures that the fragment controller is initialized. */ private void ensureFragmentController() { if (mFragmentController == null) { this.mFragmentController = instantiateFragmentController(); this.mFragmentController.setFragmentContainerId(R.id.ui_container); } } /** * Creates a new instance of FragmentController for the context that uses this delegate. * * @return New FragmentController instance. */ @NonNull FragmentController instantiateFragmentController() { return new FragmentController((FragmentActivity) mContext); } /** * Pops stack with fragments of the associated activity via {@link FragmentManager#popBackStack()} * * @return {@code True} if the stack has ben popped, {@code false} otherwise. */ public boolean popFragmentsBackStack() { final FragmentManager fragmentManager = ((FragmentActivity) mContext).getSupportFragmentManager(); if (fragmentManager.getBackStackEntryCount() > 0) { fragmentManager.popBackStack(); return true; } return false; } /** * Searches for current fragment displayed in container that is used by {@link FragmentController} * of this delegate to show fragments in the context of the associated activity. * * @return Instance of current fragment found via {@link FragmentController#findFragmentById(int)} * where as container id is used {@link FragmentController#getFragmentContainerId()} or {@code null} * if there is no fragment displayed. */ @Nullable public Fragment findCurrentFragment() { return mFragmentController != null ? mFragmentController.findFragmentById(mFragmentController.getFragmentContainerId()) : null; } /** */ @NonNull @Override DialogController instantiateDialogController() { return new DialogController((FragmentActivity) mContext); } /** * Inner classes =============================================================================== */ }