All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.ioc.commons.impl.android.flowcontrol.placecontroller.AndroidPlaceController Maven / Gradle / Ivy

package org.ioc.commons.impl.android.flowcontrol.placecontroller;

import java.util.LinkedList;
import java.util.List;
import java.util.Objects;

import org.ioc.commons.flowcontrol.activitymapper.IsActivityManager;
import org.ioc.commons.flowcontrol.eventbus.EventBusBinder;
import org.ioc.commons.flowcontrol.placecontroller.HasPlaceData;
import org.ioc.commons.flowcontrol.placecontroller.IsPlace;
import org.ioc.commons.flowcontrol.placecontroller.PlaceController;
import org.ioc.commons.impl.android.flowcontrol.activitymapper.Place;
import org.ioc.commons.impl.android.flowcontrol.activitymapper.Place.Type;
import org.ioc.commons.impl.android.flowcontrol.eventbus.AndroidEventBusImpl;
import org.ioc.commons.ui.IsWidget;
import org.ioc.commons.utils.Format;
import org.ioc.commons.utils.FormatterLogger;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentManager.BackStackEntry;
import android.support.v4.app.FragmentTransaction;
import android.view.HasFrameLayout;
import android.widget.FrameLayout;
import android.widget.Toast;

public class AndroidPlaceController implements PlaceController {

	private static final FormatterLogger logger = FormatterLogger.getLogger(AndroidPlaceController.class);

	private static final String PLACE_KEY = "PLACE";

	public interface PlaceMapper {
		

> Place

getPlace(P place, Object... params); } private static boolean strictMode = true; private final LinkedList forwardPlaces = new LinkedList(); private Place> firstPlace; private AndroidEventBusImpl eventBus; private final PlaceMapper mapper; private final Context context; private boolean firstPlaceHandled; public AndroidPlaceController(Context context, PlaceMapper placeMapper) { this.context = context; this.mapper = placeMapper; init(); } private void init() { this.eventBus = new AndroidEventBusImpl(context.getApplicationContext(), true); } @Override public

> void initPlaceController(P firstPlaceId, Object... params) { Place

firstPlace = this.mapper.getPlace(firstPlaceId, params); assert (firstPlace != null) : "The default cannot be null"; this.firstPlace = firstPlace; } @Override public

> void initPlaceController(boolean handleCurrentPlaceNow, P firstPlaceId, Object... params) { this.initPlaceController(firstPlaceId, params); if (handleCurrentPlaceNow) { this.handleCurrentPlace(); } } @Override public

> void goTo(P placeId, Object... params) { goTo(true, placeId, params); } @Override public

> void goTo(boolean addToHistoryStack, P placeId, Object... params) { Place

place = this.mapper.getPlace(placeId, params); goTo(addToHistoryStack, place); } @Override public void goTo(HasPlaceData placeData) { goTo(true, placeData); } @Override public void goTo(boolean addToHistoryStack, HasPlaceData placeData) { if (placeData == null) { throw new NullPointerException("Cannot go to a null place"); } if (!(placeData instanceof Place)) { throw new IllegalArgumentException( Format.substitute("placeData parameter should be an instance of {0} but found {1}", Place.class, placeData.getClass())); } // if (context == null) { // IsActivityManager activityManager = // this.activityManagerProvider.getActivityManager(); // IsWidget display = activityManager.getDisplay(); // // throw new IllegalArgumentException(Format.substitute( // "display should be an instance of {0} or {1} but found {2}", // Context.class, HasContext.class, // display != null ? display.getClass() : "-- null --")); // } Place place = (Place) placeData; goTo(context, place, addToHistoryStack); } // private Context getContext() { // IsActivityManager activityManager = // this.activityManagerProvider.getActivityManager(); // IsWidget display = activityManager.getDisplay(); // // Context context = null; // // if (display instanceof HasContext) { // context = ((HasContext) display).getContext(); // } else if (display instanceof Context) { // context = (Context) display; // } // return context; // } protected void goTo(Context context, Place place, boolean addToHistoryStack) { Enum placeId = place.getPlaceId(); switch (place.getType()) { case ACTIVITY_PLACE: Class toActivity = place.getActivity(); startActivity(placeId, context, toActivity, place.getForResultRequestCode(), place.getExtras()); break; case FRAGMENT_PLACE: showFragment(placeId, place.getFragment(), context, place.equals(firstPlace), addToHistoryStack); break; case INTENT_PLACE: startActivity(placeId, context, place.getIntent(), place.getForResultRequestCode()); break; } } protected

> void startActivity(P placeId, Context context, Class toActivity, Integer forResultRequestCode, Bundle extras) { Intent i = new Intent(context, toActivity); if (extras != null) { i.putExtras(extras); } startActivity(placeId, context, i, forResultRequestCode); } protected

> void startActivity(P placeId, Context context, Intent i, Integer forResultRequestCode) { i.putExtra(PLACE_KEY, placeId.ordinal()); startActivity(placeId, context, i, true, forResultRequestCode); } protected

> void showFragment(final P placeId, final Fragment fragment, Context context, final boolean firstPlace, final boolean addToHistoryStack) { IsActivityManager activityManager = ensureIsActivityManager(context); IsWidget display = activityManager.getDisplay(); Object view = display.asWidget(); if (view instanceof HasFrameLayout) { view = ((HasFrameLayout) view).getFrameLayout(); if (view == null) { throw new IllegalArgumentException(Format.substitute("Required frame layout instance but found null")); } } if (!(view instanceof FrameLayout)) { throw new IllegalArgumentException(Format.substitute( "Required {0} as display for controlling fragment places but found {1}", FrameLayout.class.getSimpleName(), view != null ? view.getClass() : "-- null --")); } final FrameLayout frameLayout = (FrameLayout) view; if (context instanceof FragmentActivity) { final FragmentActivity host = (FragmentActivity) context; if (host.isDestroyed()) { throw new IllegalArgumentException("Invalid destroyed activity as context"); } host.runOnUiThread(new Runnable() { @Override public void run() { String activeTag = getActiveFragmentTag(host); // Fragment visibleFragment = getVisibleFragment(host); if (Objects.equals(activeTag, getTag(placeId))) { // if (Objects.equals(visibleFragment, fragment)) { return; } frameLayout.removeAllViews(); if (firstPlace && !firstPlaceHandled) { // // Check that the activity is using the layout // version // with // // the fragment_container FrameLayout // if (findViewById(R.id.fragment_container) != null) { // // However, if we're being restored from a previous // state, // then we don't need to do anything and should return // or // else // we could end up with overlapping fragments. // if (savedInstanceState != null) { // return; // } host.getSupportFragmentManager().beginTransaction() .add(frameLayout.getId(), fragment, getTag(placeId)).commitAllowingStateLoss(); } else { FragmentTransaction tx = host.getSupportFragmentManager().beginTransaction() .replace(frameLayout.getId(), fragment, getTag(placeId)); if (addToHistoryStack) { tx.addToBackStack(getTag(placeId)); } tx.commitAllowingStateLoss(); } logBackStack(host, false); eventBus.fireEvent(Event.PlaceChanged, placeId); } }); } else { throw new IllegalArgumentException(Format.substitute( "Required context which extends from {0} or {1} for controlling fragment places", FragmentActivity.class.getSimpleName(), Activity.class.getSimpleName())); } } private IsActivityManager ensureIsActivityManager(Context context) { if (!(context instanceof IsActivityManager)) { throw new IllegalArgumentException(Format.substitute( "Required context which implements {0} for controlling fragment places", IsActivityManager.class.getSimpleName())); } IsActivityManager activityManager = (IsActivityManager) context; return activityManager; } protected

> void showFragment(final P placeId, final android.app.Fragment fragment, Context context, final boolean firstPlace, final boolean addToHistoryStack) { IsActivityManager activityManager = ensureIsActivityManager(context); IsWidget display = activityManager.getDisplay(); Object view = display.asWidget(); if (!(view instanceof FrameLayout)) { throw new IllegalArgumentException(Format.substitute( "Required {0} as display for controlling fragment places", FrameLayout.class.getSimpleName())); } final FrameLayout frameLayout = (FrameLayout) display; if (context instanceof Activity) { final Activity host = (Activity) context; host.runOnUiThread(new Runnable() { @Override public void run() { String activeTag = getActiveFragmentTag(host); // Fragment visibleFragment = getVisibleFragment(host); if (Objects.equals(activeTag, getTag(placeId))) { // if (Objects.equals(visibleFragment, fragment)) { return; } frameLayout.removeAllViews(); if (firstPlace && !firstPlaceHandled) { host.getFragmentManager().beginTransaction() .add(frameLayout.getId(), fragment, getTag(placeId)).commitAllowingStateLoss(); } else { android.app.FragmentTransaction tx = host.getFragmentManager().beginTransaction() .replace(frameLayout.getId(), fragment, getTag(placeId)); if (addToHistoryStack) { tx.addToBackStack(getTag(placeId)); } tx.commitAllowingStateLoss(); } logBackStack(host, false); eventBus.fireEvent(Event.PlaceChanged, placeId); } }); } else { throw new IllegalArgumentException(Format.substitute( "Required context which extends from {0} or {1} for controlling fragment places", FragmentActivity.class.getSimpleName(), Activity.class.getSimpleName())); } } private

> void startActivity(P placeId, Context context, Intent intent, boolean clearForwardPlaces, Integer forResultRequestCode) { if (forResultRequestCode == null) { context.startActivity(intent); } else { if (!(context instanceof Activity)) { throw new IllegalArgumentException("Cannot start an activity when Context is not another Activity"); } Activity activity = (Activity) context; activity.startActivityForResult(intent, forResultRequestCode); } this.eventBus.fireEvent(Event.PlaceChanged, placeId); if (clearForwardPlaces) { forwardPlaces.clear(); } } @Override public void goBack() { forwardPlaces.add(this.getCurrentPlaceData()); Activity ca = getActivity(); if (ca == null) { throw new IllegalArgumentException("Required context activity but found null"); } ca.onBackPressed(); } private Activity getActivity() { if (context != null && !(context instanceof Activity)) { throw new IllegalArgumentException("Cannot start an activity when Context is not another Activity. Found " + context); } Activity activity = (Activity) context; return activity; } @Override public void goForward() { if (!forwardPlaces.isEmpty()) { HasPlaceData placeData = forwardPlaces.removeLast(); assert (placeData instanceof Place) : "place parameter should be an instance of " + Place.class; Place place = (Place) placeData; goTo(place); } } @Override public void appendPlaceInHistory(HasPlaceData place) { forwardPlaces.addFirst(place); } @SuppressLint("Assert") @Override public HasPlaceData getCurrentPlaceData() { Activity where = getActivity(); assert (!strictMode || (where == null) || (where instanceof HasPlaceData) || (where instanceof FragmentActivity)) : "There is no possible to introduce a Place which does not inherit from HasPlaceData in strit mode. Disable strict mode setting AndroidPlaceController.setStrictMode(false). Where=" + where; if (where instanceof FragmentActivity) { // String curFragmentTag = getActiveFragmentTag((FragmentActivity) // where); // if (curFragmentTag != null) { // Fragment fragment = ((FragmentActivity) // where).getSupportFragmentManager().findFragmentByTag( // curFragmentTag); Fragment fragment = getVisibleFragment((FragmentActivity) where); if (fragment != null) { String tag = fragment.getTag(); try { int sep = tag != null ? tag.lastIndexOf('.') : -1; String className = tag.substring(0, sep); String enumValue = tag.substring(sep + 1); Class enumClazz = Class.forName(className); @SuppressWarnings("unchecked") Enum curPlace = Enum.valueOf(enumClazz, enumValue); return new Place>(curPlace, fragment); } catch (Exception e) { if (this.firstPlace != null) { logger.warn(e, "Unknown current place: '{0}'. Known places from: {1}", tag, this.firstPlace .getPlaceId().getClass()); } else { logger.warn(e, "Unknown current place: '{0}'. Unknown valid places.", tag); } /* * Unknown place */ return null; } } else { return null; } } return (where instanceof HasPlaceData) ? (HasPlaceData) where : null; } private Fragment getVisibleFragment(FragmentActivity fa) { List fragments = fa.getSupportFragmentManager().getFragments(); if (fragments != null) { for (int i = fragments.size() - 1; i >= 0; i--) { Fragment f = fragments.get(i); if (f != null && f.getUserVisibleHint()) { return f; } } } return null; } private String getActiveFragmentTag(FragmentActivity fa) { if (fa.getSupportFragmentManager().getBackStackEntryCount() == 0) { return null; } String tag = fa.getSupportFragmentManager() .getBackStackEntryAt(fa.getSupportFragmentManager().getBackStackEntryCount() - 1).getName(); return tag; } private String getActiveFragmentTag(Activity fa) { if (fa.getFragmentManager().getBackStackEntryCount() == 0) { return null; } String tag = fa.getFragmentManager().getBackStackEntryAt(fa.getFragmentManager().getBackStackEntryCount() - 1) .getName(); return tag; } private String getPreviousFragmentTag(FragmentActivity fa) { if (fa.getSupportFragmentManager().getBackStackEntryCount() < 2) { return null; } String tag = fa.getSupportFragmentManager() .getBackStackEntryAt(fa.getSupportFragmentManager().getBackStackEntryCount() - 2).getName(); return tag; } public void logBackStack(FragmentActivity fa, boolean toast) { if (fa.getSupportFragmentManager().getBackStackEntryCount() == 0) { logger.debug("Empty backstack"); } for (int i = 0; i < fa.getSupportFragmentManager().getBackStackEntryCount(); i++) { BackStackEntry entry = fa.getSupportFragmentManager().getBackStackEntryAt(i); String message = Format.substitute("Backstack Pos: {0} Id: {1} Name: {2}", i, entry.getId(), entry.getName()); logger.debug(message); if (toast) { Toast.makeText(fa, message, Toast.LENGTH_SHORT).show(); } } } public void logBackStack(Activity fa, boolean toast) { if (fa.getFragmentManager().getBackStackEntryCount() == 0) { logger.debug("Empty backstack"); } for (int i = 0; i < fa.getFragmentManager().getBackStackEntryCount(); i++) { android.app.FragmentManager.BackStackEntry entry = fa.getFragmentManager().getBackStackEntryAt(i); String message = Format.substitute("Backstack Pos: {0} Id: {1} Name: {2}", i, entry.getId(), entry.getName()); logger.debug(message); if (toast) { Toast.makeText(fa, message, Toast.LENGTH_SHORT).show(); } } } @Override public void handleCurrentPlace() { logger.entering("handleCurrentPlace"); logger.debug("Handling curren place..."); Activity ca = getActivity(); // if (!this.firstPlaceHandled // && this.firstPlace != null // && ((ca == null && this.firstPlace.getType() != Type.FRAGMENT_PLACE) // || (this.firstPlace.getType() == Type.FRAGMENT_PLACE && ca instanceof // FragmentActivity))) { // this.firstPlaceHandled = true; // logger.debug("Going to first place {0} at the first time", // firstPlace); // this.goTo(firstPlace); // } else { HasPlaceData cpd = getCurrentPlaceData(); if (cpd != null) { logger.debug("Notifying detected placed changed", firstPlace); this.eventBus.fireEvent(Event.PlaceChanged, cpd.getPlaceId()); } else if (this.firstPlace != null && (this.firstPlace.getType() == Type.FRAGMENT_PLACE && ca instanceof FragmentActivity)) { /* * When current place is null, is a fragment, and the current place * (the current place) is not set, we go to the main fragment (It * happens when activity has been created again and the previous * fragment has not been saved) */ logger.debug("Going to first place {0} again", firstPlace); this.firstPlaceHandled = true; this.goTo(firstPlace); } // } logger.exiting("handleCurrentPlace"); } @Override public void notifyPlaceChanged() { HasPlaceData cpd = getCurrentPlaceData(); if (cpd != null) { this.eventBus.fireEvent(Event.PlaceChanged, cpd.getPlaceId()); } } @Override public

> HasPlaceData getPlaceData(P placeId, Object... params) { Place

androidPlace = this.mapper.getPlace(placeId, params); return (HasPlaceData) androidPlace; } @Override public EventBusBinder eventbus() { return this.eventBus; } @Override public HasPlaceData getFirstPlace() { return this.firstPlace; } protected boolean isFirstPlace(HasPlaceData placeData) { return this.firstPlace != null && this.firstPlace.equals(placeData); } @Override public boolean isCurrentPlaceFirstPlace() { return this.isFirstPlace(this.getCurrentPlaceData()); } /* * (non-Javadoc) * * @see * org.ioc.commons.flowcontrol.placecontroller.PlaceController#currentPlaceAsUrl * () */ @Override public String currentPlaceAsUrl() { Activity ca = getActivity(); if (ca == null) { throw new IllegalArgumentException("Required context activity but found null"); } Intent in = ca != null ? ca.getIntent() : null; Uri data = in != null ? in.getData() : null; return data != null ? data.toString() : ""; } @Override public

> String getPlaceAsUrl(P placeId, Object... params) { Activity ca = getActivity(); if (ca == null) { throw new IllegalArgumentException("Required context activity but found null"); } Place

place = this.mapper.getPlace(placeId, params); Intent in = null; Bundle extras = place.getExtras(); switch (place.getType()) { case ACTIVITY_PLACE: in = new Intent(ca, place.getActivity()); break; case FRAGMENT_PLACE: in = new Intent(ca, place.getFragment().getActivity() != null ? place.getFragment().getActivity() .getClass() : place.getFragment().getClass()); break; default: throw new IllegalArgumentException("Unknow type " + place.getType()); } in.putExtra(PLACE_KEY, placeId.ordinal()); if (extras != null) { in.putExtras(extras); } Uri data = in != null ? in.getData() : null; return data != null ? data.toString() : ""; } @Override public String getPlaceAsUrl(HasPlaceData placeData) { assert (placeData instanceof Intent) : "place parameter should be an instance of " + Intent.class; // Activity ca = currentActivityProvider.getCurrentActivity(); Intent in = (Intent) placeData; Uri data = in != null ? in.getData() : null; return data != null ? data.toString() : ""; } public static boolean isStrictMode() { return strictMode; } public static void setStrictMode(boolean strictMode) { AndroidPlaceController.strictMode = strictMode; } @Override public boolean removeCurrentPlaceFromHistory() { Activity where = getActivity(); if (where instanceof FragmentActivity) { FragmentManager sfm = ((FragmentActivity) where).getSupportFragmentManager(); return sfm.popBackStackImmediate(); // return true; } return false; } @Override public

> void goBackOrTo(P placeId, Object... params) { Activity where = getActivity(); String prevTag = null; if (where instanceof FragmentActivity) { prevTag = getPreviousFragmentTag((FragmentActivity) where); } if (!Objects.equals(prevTag, getTag(placeId))) { goTo(placeId, params); } else { goBack(); } } protected

> String getTag(final P placeId) { return placeId.getClass().getName() + "." + placeId.name(); } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy