package android.support.v4.app;
import android.content.Context;
import android.content.res.Configuration;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Parcel;
import android.os.Parcelable;
import android.support.v4.util.DebugUtils;
import android.support.v4.util.LogWriter;
import android.util.Log;
import android.util.SparseArray;
import android.view.animation.AccelerateInterpolator;
import android.view.animation.AlphaAnimation;
import android.view.animation.Animation;
import android.view.animation.AnimationSet;
import android.view.animation.AnimationUtils;
import android.view.animation.DecelerateInterpolator;
import android.view.animation.Interpolator;
import android.view.animation.ScaleAnimation;
import android.view.animation.Animation.AnimationListener;
import android.view.View;
import android.view.ViewGroup;
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import com.actionbarsherlock.view.Menu;
import com.actionbarsherlock.view.MenuInflater;
import com.actionbarsherlock.view.MenuItem;
}
}
@Deprecated
return beginTransaction();
}
public static final int POP_BACK_STACK_INCLUSIVE = 1<<0;
public abstract void putFragment(Bundle bundle, String key, Fragment fragment);
public abstract Fragment
getFragment(Bundle bundle, String key);
public abstract void dump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args);
FragmentManagerImpl.DEBUG = enabled;
}
}
FragmentState[] mActive;
int[] mAdded;
BackStackState[] mBackStack;
}
mActive = in.createTypedArray(FragmentState.CREATOR);
mAdded = in.createIntArray();
mBackStack = in.createTypedArray(BackStackState.CREATOR);
}
return 0;
}
dest.writeTypedArray(mActive, flags);
dest.writeIntArray(mAdded);
dest.writeTypedArray(mBackStack, flags);
}
public static final Parcelable.Creator<FragmentManagerState> CREATOR
= new Parcelable.Creator<FragmentManagerState>() {
return new FragmentManagerState(in);
}
public FragmentManagerState[]
newArray(
int size) {
return new FragmentManagerState[size];
}
};
}
static boolean DEBUG = false;
static final String TAG = "FragmentManager";
static final boolean HONEYCOMB = android.os.Build.VERSION.SDK_INT >= 11;
static final String TARGET_REQUEST_CODE_STATE_TAG = "android:target_req_state";
static final String TARGET_STATE_TAG = "android:target_state";
static final String VIEW_STATE_TAG = "android:view_state";
static final String USER_VISIBLE_HINT_TAG = "android:user_visible_hint";
ArrayList<Runnable> mPendingActions;
Runnable[] mTmpActions;
boolean mExecutingActions;
ArrayList<Fragment> mActive;
ArrayList<Fragment> mAdded;
ArrayList<Integer> mAvailIndices;
ArrayList<BackStackRecord> mBackStack;
ArrayList<Fragment> mCreatedMenus;
ArrayList<BackStackRecord> mBackStackIndices;
ArrayList<Integer> mAvailBackStackIndices;
ArrayList<OnBackStackChangedListener> mBackStackChangeListeners;
int mCurState = Fragment.INITIALIZING;
FragmentActivity mActivity;
boolean mNeedMenuInvalidate;
boolean mStateSaved;
boolean mDestroyed;
String mNoTransactionsBecause;
boolean mHavePendingDeferredStart;
Bundle mStateBundle = null;
SparseArray<Parcelable> mStateArray = null;
Runnable mExecCommit = new Runnable() {
@Override
execPendingActions();
}
};
@Override
return new BackStackRecord(this);
}
@Override
return execPendingActions();
}
@Override
enqueueAction(new Runnable() {
@Override
public void run() {
popBackStackState(mActivity.mHandler, null, -1, 0);
}
}, false);
}
@Override
checkStateLoss();
executePendingTransactions();
return popBackStackState(mActivity.mHandler, null, -1, 0);
}
@Override
public void popBackStack(
final String name,
final int flags) {
enqueueAction(new Runnable() {
@Override
public void run() {
popBackStackState(mActivity.mHandler, name, -1, flags);
}
}, false);
}
@Override
checkStateLoss();
executePendingTransactions();
return popBackStackState(mActivity.mHandler, name, -1, flags);
}
@Override
if (id < 0) {
throw new IllegalArgumentException("Bad id: " + id);
}
enqueueAction(new Runnable() {
@Override
public void run() {
popBackStackState(mActivity.mHandler, null, id, flags);
}
}, false);
}
@Override
checkStateLoss();
executePendingTransactions();
if (id < 0) {
throw new IllegalArgumentException("Bad id: " + id);
}
return popBackStackState(mActivity.mHandler, null, id, flags);
}
@Override
return mBackStack != null ? mBackStack.size() : 0;
}
@Override
return mBackStack.get(index);
}
@Override
if (mBackStackChangeListeners == null) {
mBackStackChangeListeners = new ArrayList<OnBackStackChangedListener>();
}
mBackStackChangeListeners.add(listener);
}
@Override
if (mBackStackChangeListeners != null) {
mBackStackChangeListeners.remove(listener);
}
}
@Override
public void putFragment(Bundle bundle, String key, Fragment fragment) {
if (fragment.mIndex < 0) {
throw new IllegalStateException("Fragment " + fragment
+ " is not currently in the FragmentManager");
}
bundle.putInt(key, fragment.mIndex);
}
@Override
public Fragment
getFragment(Bundle bundle, String key) {
int index = bundle.getInt(key, -1);
if (index == -1) {
return null;
}
if (index >= mActive.size()) {
throw new IllegalStateException("Fragement no longer exists for key "
+ key + ": index " + index);
}
Fragment f = mActive.get(index);
if (f == null) {
throw new IllegalStateException("Fragement no longer exists for key "
+ key + ": index " + index);
}
return f;
}
@Override
if (fragment.mIndex < 0) {
throw new IllegalStateException("Fragment " + fragment
+ " is not currently in the FragmentManager");
}
if (fragment.mState > Fragment.INITIALIZING) {
Bundle result = saveFragmentBasicState(fragment);
return result != null ? new Fragment.SavedState(result) : null;
}
return null;
}
@Override
StringBuilder sb = new StringBuilder(128);
sb.append("FragmentManager{");
sb.append(Integer.toHexString(System.identityHashCode(this)));
sb.append(" in ");
DebugUtils.buildShortClassTag(mActivity, sb);
sb.append("}}");
return sb.toString();
}
@Override
public void dump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) {
String innerPrefix = prefix + " ";
int N;
if (mActive != null) {
N = mActive.size();
if (N > 0) {
writer.print(prefix); writer.print("Active Fragments in ");
writer.print(Integer.toHexString(System.identityHashCode(this)));
writer.println(":");
for (int i=0; i<N; i++) {
Fragment f = mActive.get(i);
writer.print(prefix); writer.print(" #"); writer.print(i);
writer.print(": "); writer.println(f);
if (f != null) {
f.dump(innerPrefix, fd, writer, args);
}
}
}
}
if (mAdded != null) {
N = mAdded.size();
if (N > 0) {
writer.print(prefix); writer.println("Added Fragments:");
for (int i=0; i<N; i++) {
Fragment f = mAdded.get(i);
writer.print(prefix); writer.print(" #"); writer.print(i);
writer.print(": "); writer.println(f.toString());
}
}
}
if (mCreatedMenus != null) {
N = mCreatedMenus.size();
if (N > 0) {
writer.print(prefix); writer.println("Fragments Created Menus:");
for (int i=0; i<N; i++) {
Fragment f = mCreatedMenus.get(i);
writer.print(prefix); writer.print(" #"); writer.print(i);
writer.print(": "); writer.println(f.toString());
}
}
}
if (mBackStack != null) {
N = mBackStack.size();
if (N > 0) {
writer.print(prefix); writer.println("Back Stack:");
for (int i=0; i<N; i++) {
BackStackRecord bs = mBackStack.get(i);
writer.print(prefix); writer.print(" #"); writer.print(i);
writer.print(": "); writer.println(bs.toString());
bs.dump(innerPrefix, fd, writer, args);
}
}
}
synchronized (this) {
if (mBackStackIndices != null) {
N = mBackStackIndices.size();
if (N > 0) {
writer.print(prefix); writer.println("Back Stack Indices:");
for (int i=0; i<N; i++) {
BackStackRecord bs = mBackStackIndices.get(i);
writer.print(prefix); writer.print(" #"); writer.print(i);
writer.print(": "); writer.println(bs);
}
}
}
if (mAvailBackStackIndices != null && mAvailBackStackIndices.size() > 0) {
writer.print(prefix); writer.print("mAvailBackStackIndices: ");
writer.println(Arrays.toString(mAvailBackStackIndices.toArray()));
}
}
if (mPendingActions != null) {
N = mPendingActions.size();
if (N > 0) {
writer.print(prefix); writer.println("Pending Actions:");
for (int i=0; i<N; i++) {
Runnable r = mPendingActions.get(i);
writer.print(prefix); writer.print(" #"); writer.print(i);
writer.print(": "); writer.println(r);
}
}
}
writer.print(prefix); writer.println("FragmentManager misc state:");
writer.print(prefix); writer.print(" mCurState="); writer.print(mCurState);
writer.print(" mStateSaved="); writer.print(mStateSaved);
writer.print(" mDestroyed="); writer.println(mDestroyed);
if (mNeedMenuInvalidate) {
writer.print(prefix); writer.print(" mNeedMenuInvalidate=");
writer.println(mNeedMenuInvalidate);
}
if (mNoTransactionsBecause != null) {
writer.print(prefix); writer.print(" mNoTransactionsBecause=");
writer.println(mNoTransactionsBecause);
}
if (mAvailIndices != null && mAvailIndices.size() > 0) {
writer.print(prefix); writer.print(" mAvailIndices: ");
writer.println(Arrays.toString(mAvailIndices.toArray()));
}
}
static final Interpolator DECELERATE_QUINT = new DecelerateInterpolator(2.5f);
static final Interpolator DECELERATE_CUBIC = new DecelerateInterpolator(1.5f);
static final Interpolator ACCELERATE_QUINT = new AccelerateInterpolator(2.5f);
static final Interpolator ACCELERATE_CUBIC = new AccelerateInterpolator(1.5f);
static final int ANIM_DUR = 220;
float endScale, float startAlpha, float endAlpha) {
AnimationSet set = new AnimationSet(false);
ScaleAnimation scale = new ScaleAnimation(startScale, endScale, startScale, endScale,
Animation.RELATIVE_TO_SELF, .5f, Animation.RELATIVE_TO_SELF, .5f);
scale.setInterpolator(DECELERATE_QUINT);
scale.setDuration(ANIM_DUR);
set.addAnimation(scale);
AlphaAnimation alpha = new AlphaAnimation(startAlpha, endAlpha);
alpha.setInterpolator(DECELERATE_CUBIC);
alpha.setDuration(ANIM_DUR);
set.addAnimation(alpha);
return set;
}
AlphaAnimation anim = new AlphaAnimation(start, end);
anim.setInterpolator(DECELERATE_CUBIC);
anim.setDuration(ANIM_DUR);
return anim;
}
Animation
loadAnimation(Fragment fragment,
int transit,
boolean enter,
int transitionStyle) {
Animation animObj = fragment.onCreateAnimation(transit, enter,
fragment.mNextAnim);
if (animObj != null) {
return animObj;
}
if (fragment.mNextAnim != 0) {
Animation anim = AnimationUtils.loadAnimation(mActivity, fragment.mNextAnim);
if (anim != null) {
return anim;
}
}
if (transit == 0) {
return null;
}
int styleIndex = transitToStyleIndex(transit, enter);
if (styleIndex < 0) {
return null;
}
switch (styleIndex) {
case ANIM_STYLE_OPEN_ENTER:
return makeOpenCloseAnimation(mActivity, 1.125f, 1.0f, 0, 1);
case ANIM_STYLE_OPEN_EXIT:
return makeOpenCloseAnimation(mActivity, 1.0f, .975f, 1, 0);
case ANIM_STYLE_CLOSE_ENTER:
return makeOpenCloseAnimation(mActivity, .975f, 1.0f, 0, 1);
case ANIM_STYLE_CLOSE_EXIT:
return makeOpenCloseAnimation(mActivity, 1.0f, 1.075f, 1, 0);
case ANIM_STYLE_FADE_ENTER:
return makeFadeAnimation(mActivity, 0, 1);
case ANIM_STYLE_FADE_EXIT:
return makeFadeAnimation(mActivity, 1, 0);
}
if (transitionStyle == 0 && mActivity.getWindow() != null) {
transitionStyle = mActivity.getWindow().getAttributes().windowAnimations;
}
if (transitionStyle == 0) {
return null;
}
return null;
}
if (f.mDeferStart) {
if (mExecutingActions) {
mHavePendingDeferredStart = true;
return;
}
f.mDeferStart = false;
moveToState(f, mCurState, 0, 0);
}
}
void moveToState(Fragment f,
int newState,
int transit,
int transitionStyle) {
if (!f.mAdded && newState > Fragment.CREATED) {
newState = Fragment.CREATED;
}
if (f.mRemoving && newState > f.mState) {
newState = f.mState;
}
if (f.mDeferStart && f.mState < Fragment.STARTED && newState > Fragment.STOPPED) {
newState = Fragment.STOPPED;
}
if (f.mState < newState) {
if (f.mFromLayout && !f.mInLayout) {
return;
}
if (f.mAnimatingAway != null) {
f.mAnimatingAway = null;
moveToState(f, f.mStateAfterAnimating, 0, 0);
}
switch (f.mState) {
case Fragment.INITIALIZING:
if (DEBUG) Log.v(TAG, "moveto CREATED: " + f);
if (f.mSavedFragmentState != null) {
f.mSavedViewState = f.mSavedFragmentState.getSparseParcelableArray(
FragmentManagerImpl.VIEW_STATE_TAG);
f.mTarget = getFragment(f.mSavedFragmentState,
FragmentManagerImpl.TARGET_STATE_TAG);
if (f.mTarget != null) {
f.mTargetRequestCode = f.mSavedFragmentState.getInt(
FragmentManagerImpl.TARGET_REQUEST_CODE_STATE_TAG, 0);
}
f.mUserVisibleHint = f.mSavedFragmentState.getBoolean(
FragmentManagerImpl.USER_VISIBLE_HINT_TAG, true);
if (!f.mUserVisibleHint) {
f.mDeferStart = true;
if (newState > Fragment.STOPPED) {
newState = Fragment.STOPPED;
}
}
}
f.mActivity = mActivity;
f.mFragmentManager = mActivity.mFragments;
f.mCalled = false;
f.onAttach(mActivity);
if (!f.mCalled) {
throw new SuperNotCalledException("Fragment " + f
+ " did not call through to super.onAttach()");
}
mActivity.onAttachFragment(f);
if (!f.mRetaining) {
f.mCalled = false;
f.onCreate(f.mSavedFragmentState);
if (!f.mCalled) {
throw new SuperNotCalledException("Fragment " + f
+ " did not call through to super.onCreate()");
}
}
f.mRetaining = false;
if (f.mFromLayout) {
f.mView = f.onCreateView(f.getLayoutInflater(f.mSavedFragmentState),
null, f.mSavedFragmentState);
if (f.mView != null) {
f.mInnerView = f.mView;
f.mView = NoSaveStateFrameLayout.wrap(f.mView);
if (f.mHidden) f.mView.setVisibility(View.GONE);
f.onViewCreated(f.mView, f.mSavedFragmentState);
} else {
f.mInnerView = null;
}
}
case Fragment.CREATED:
if (newState > Fragment.CREATED) {
if (DEBUG) Log.v(TAG, "moveto ACTIVITY_CREATED: " + f);
if (!f.mFromLayout) {
ViewGroup container = null;
if (f.mContainerId != 0) {
container = (ViewGroup)mActivity.findViewById(f.mContainerId);
if (container == null && !f.mRestored) {
throw new IllegalArgumentException("No view found for id 0x"
+ Integer.toHexString(f.mContainerId)
+ " for fragment " + f);
}
}
f.mContainer = container;
f.mView = f.onCreateView(f.getLayoutInflater(f.mSavedFragmentState),
container, f.mSavedFragmentState);
if (f.mView != null) {
f.mInnerView = f.mView;
f.mView = NoSaveStateFrameLayout.wrap(f.mView);
if (container != null) {
Animation anim = loadAnimation(f, transit, true,
transitionStyle);
if (anim != null) {
f.mView.startAnimation(anim);
}
container.addView(f.mView);
}
if (f.mHidden) f.mView.setVisibility(View.GONE);
f.onViewCreated(f.mView, f.mSavedFragmentState);
} else {
f.mInnerView = null;
}
}
f.mCalled = false;
f.onActivityCreated(f.mSavedFragmentState);
if (!f.mCalled) {
throw new SuperNotCalledException("Fragment " + f
+ " did not call through to super.onActivityCreated()");
}
if (f.mView != null) {
f.restoreViewState();
}
f.mSavedFragmentState = null;
}
case Fragment.ACTIVITY_CREATED:
case Fragment.STOPPED:
if (newState > Fragment.STOPPED) {
if (DEBUG) Log.v(TAG, "moveto STARTED: " + f);
f.mCalled = false;
f.performStart();
if (!f.mCalled) {
throw new SuperNotCalledException("Fragment " + f
+ " did not call through to super.onStart()");
}
}
case Fragment.STARTED:
if (newState > Fragment.STARTED) {
if (DEBUG) Log.v(TAG, "moveto RESUMED: " + f);
f.mCalled = false;
f.mResumed = true;
f.onResume();
if (!f.mCalled) {
throw new SuperNotCalledException("Fragment " + f
+ " did not call through to super.onResume()");
}
f.mSavedFragmentState = null;
f.mSavedViewState = null;
}
}
} else if (f.mState > newState) {
switch (f.mState) {
case Fragment.RESUMED:
if (newState < Fragment.RESUMED) {
if (DEBUG) Log.v(TAG, "movefrom RESUMED: " + f);
f.mCalled = false;
f.onPause();
if (!f.mCalled) {
throw new SuperNotCalledException("Fragment " + f
+ " did not call through to super.onPause()");
}
f.mResumed = false;
}
case Fragment.STARTED:
if (newState < Fragment.STARTED) {
if (DEBUG) Log.v(TAG, "movefrom STARTED: " + f);
f.mCalled = false;
f.performStop();
if (!f.mCalled) {
throw new SuperNotCalledException("Fragment " + f
+ " did not call through to super.onStop()");
}
}
case Fragment.STOPPED:
if (newState < Fragment.STOPPED) {
if (DEBUG) Log.v(TAG, "movefrom STOPPED: " + f);
f.performReallyStop();
}
case Fragment.ACTIVITY_CREATED:
if (newState < Fragment.ACTIVITY_CREATED) {
if (DEBUG) Log.v(TAG, "movefrom ACTIVITY_CREATED: " + f);
if (f.mView != null) {
if (!mActivity.isFinishing() && f.mSavedViewState == null) {
saveFragmentViewState(f);
}
}
f.mCalled = false;
f.performDestroyView();
if (!f.mCalled) {
throw new SuperNotCalledException("Fragment " + f
+ " did not call through to super.onDestroyView()");
}
if (f.mView != null && f.mContainer != null) {
Animation anim = null;
if (mCurState > Fragment.INITIALIZING && !mDestroyed) {
anim = loadAnimation(f, transit, false,
transitionStyle);
}
if (anim != null) {
final Fragment fragment = f;
f.mAnimatingAway = f.mView;
f.mStateAfterAnimating = newState;
anim.setAnimationListener(new AnimationListener() {
@Override
if (fragment.mAnimatingAway != null) {
fragment.mAnimatingAway = null;
moveToState(fragment, fragment.mStateAfterAnimating,
0, 0);
}
}
@Override
}
@Override
}
});
f.mView.startAnimation(anim);
}
f.mContainer.removeView(f.mView);
}
f.mContainer = null;
f.mView = null;
f.mInnerView = null;
}
case Fragment.CREATED:
if (newState < Fragment.CREATED) {
if (mDestroyed) {
if (f.mAnimatingAway != null) {
View v = f.mAnimatingAway;
f.mAnimatingAway = null;
v.clearAnimation();
}
}
if (f.mAnimatingAway != null) {
f.mStateAfterAnimating = newState;
newState = Fragment.CREATED;
} else {
if (DEBUG) Log.v(TAG, "movefrom CREATED: " + f);
if (!f.mRetaining) {
f.mCalled = false;
f.onDestroy();
if (!f.mCalled) {
throw new SuperNotCalledException("Fragment " + f
+ " did not call through to super.onDestroy()");
}
}
f.mCalled = false;
f.onDetach();
if (!f.mCalled) {
throw new SuperNotCalledException("Fragment " + f
+ " did not call through to super.onDetach()");
}
if (!f.mRetaining) {
makeInactive(f);
} else {
f.mActivity = null;
f.mFragmentManager = null;
}
}
}
}
}
f.mState = newState;
}
moveToState(f, mCurState, 0, 0);
}
moveToState(newState, 0, 0, always);
}
void moveToState(
int newState,
int transit,
int transitStyle,
boolean always) {
if (mActivity == null && newState != Fragment.INITIALIZING) {
throw new IllegalStateException("No activity");
}
if (!always && mCurState == newState) {
return;
}
mCurState = newState;
if (mActive != null) {
boolean loadersRunning = false;
for (int i=0; i<mActive.size(); i++) {
Fragment f = mActive.get(i);
if (f != null) {
moveToState(f, newState, transit, transitStyle);
if (f.mLoaderManager != null) {
loadersRunning |= f.mLoaderManager.hasRunningLoaders();
}
}
}
if (!loadersRunning) {
startPendingDeferredFragments();
}
if (mNeedMenuInvalidate && mActivity != null && mCurState == Fragment.RESUMED) {
mActivity.supportInvalidateOptionsMenu();
mNeedMenuInvalidate = false;
}
}
}
if (mActive == null) return;
for (int i=0; i<mActive.size(); i++) {
Fragment f = mActive.get(i);
if (f != null) {
performPendingDeferredStart(f);
}
}
}
if (f.mIndex >= 0) {
return;
}
if (mAvailIndices == null || mAvailIndices.size() <= 0) {
if (mActive == null) {
mActive = new ArrayList<Fragment>();
}
f.setIndex(mActive.size());
mActive.add(f);
} else {
f.setIndex(mAvailIndices.remove(mAvailIndices.size()-1));
mActive.set(f.mIndex, f);
}
}
if (f.mIndex < 0) {
return;
}
if (DEBUG) Log.v(TAG, "Freeing fragment index " + f.mIndex);
mActive.set(f.mIndex, null);
if (mAvailIndices == null) {
mAvailIndices = new ArrayList<Integer>();
}
mAvailIndices.add(f.mIndex);
mActivity.invalidateSupportFragmentIndex(f.mIndex);
f.initState();
}
public void addFragment(Fragment fragment,
boolean moveToStateNow) {
if (mAdded == null) {
mAdded = new ArrayList<Fragment>();
}
if (DEBUG) Log.v(TAG, "add: " + fragment);
makeActive(fragment);
if (!fragment.mDetached) {
mAdded.add(fragment);
fragment.mAdded = true;
fragment.mRemoving = false;
if (fragment.mHasMenu && fragment.mMenuVisible) {
mNeedMenuInvalidate = true;
}
if (moveToStateNow) {
moveToState(fragment);
}
}
}
public void removeFragment(Fragment fragment,
int transition,
int transitionStyle) {
if (DEBUG) Log.v(TAG, "remove: " + fragment + " nesting=" + fragment.mBackStackNesting);
final boolean inactive = !fragment.isInBackStack();
if (!fragment.mDetached || inactive) {
mAdded.remove(fragment);
if (fragment.mHasMenu && fragment.mMenuVisible) {
mNeedMenuInvalidate = true;
}
fragment.mAdded = false;
fragment.mRemoving = true;
moveToState(fragment, inactive ? Fragment.INITIALIZING : Fragment.CREATED,
transition, transitionStyle);
}
}
public void hideFragment(Fragment fragment,
int transition,
int transitionStyle) {
if (DEBUG) Log.v(TAG, "hide: " + fragment);
if (!fragment.mHidden) {
fragment.mHidden = true;
if (fragment.mView != null) {
Animation anim = loadAnimation(fragment, transition, true,
transitionStyle);
if (anim != null) {
fragment.mView.startAnimation(anim);
}
fragment.mView.setVisibility(View.GONE);
}
if (fragment.mAdded && fragment.mHasMenu && fragment.mMenuVisible) {
mNeedMenuInvalidate = true;
}
fragment.onHiddenChanged(true);
}
}
public void showFragment(Fragment fragment,
int transition,
int transitionStyle) {
if (DEBUG) Log.v(TAG, "show: " + fragment);
if (fragment.mHidden) {
fragment.mHidden = false;
if (fragment.mView != null) {
Animation anim = loadAnimation(fragment, transition, true,
transitionStyle);
if (anim != null) {
fragment.mView.startAnimation(anim);
}
fragment.mView.setVisibility(View.VISIBLE);
}
if (fragment.mAdded && fragment.mHasMenu && fragment.mMenuVisible) {
mNeedMenuInvalidate = true;
}
fragment.onHiddenChanged(false);
}
}
public void detachFragment(Fragment fragment,
int transition,
int transitionStyle) {
if (DEBUG) Log.v(TAG, "detach: " + fragment);
if (!fragment.mDetached) {
fragment.mDetached = true;
if (fragment.mAdded) {
mAdded.remove(fragment);
if (fragment.mHasMenu && fragment.mMenuVisible) {
mNeedMenuInvalidate = true;
}
fragment.mAdded = false;
moveToState(fragment, Fragment.CREATED, transition, transitionStyle);
}
}
}
public void attachFragment(Fragment fragment,
int transition,
int transitionStyle) {
if (DEBUG) Log.v(TAG, "attach: " + fragment);
if (fragment.mDetached) {
fragment.mDetached = false;
if (!fragment.mAdded) {
mAdded.add(fragment);
fragment.mAdded = true;
if (fragment.mHasMenu && fragment.mMenuVisible) {
mNeedMenuInvalidate = true;
}
moveToState(fragment, mCurState, transition, transitionStyle);
}
}
}
if (mActive != null) {
for (int i=mAdded.size()-1; i>=0; i--) {
Fragment f = mAdded.get(i);
if (f != null && f.mFragmentId == id) {
return f;
}
}
for (int i=mActive.size()-1; i>=0; i--) {
Fragment f = mActive.get(i);
if (f != null && f.mFragmentId == id) {
return f;
}
}
}
return null;
}
if (mActive != null && tag != null) {
for (int i=mAdded.size()-1; i>=0; i--) {
Fragment f = mAdded.get(i);
if (f != null && tag.equals(f.mTag)) {
return f;
}
}
for (int i=mActive.size()-1; i>=0; i--) {
Fragment f = mActive.get(i);
if (f != null && tag.equals(f.mTag)) {
return f;
}
}
}
return null;
}
if (mActive != null && who != null) {
for (int i=mActive.size()-1; i>=0; i--) {
Fragment f = mActive.get(i);
if (f != null && who.equals(f.mWho)) {
return f;
}
}
}
return null;
}
if (mStateSaved) {
throw new IllegalStateException(
"Can not perform this action after onSaveInstanceState");
}
if (mNoTransactionsBecause != null) {
throw new IllegalStateException(
"Can not perform this action inside of " + mNoTransactionsBecause);
}
}
public void enqueueAction(Runnable action,
boolean allowStateLoss) {
if (!allowStateLoss) {
checkStateLoss();
}
synchronized (this) {
if (mActivity == null) {
throw new IllegalStateException("Activity has been destroyed");
}
if (mPendingActions == null) {
mPendingActions = new ArrayList<Runnable>();
}
mPendingActions.add(action);
if (mPendingActions.size() == 1) {
mActivity.mHandler.removeCallbacks(mExecCommit);
mActivity.mHandler.post(mExecCommit);
}
}
}
synchronized (this) {
if (mAvailBackStackIndices == null || mAvailBackStackIndices.size() <= 0) {
if (mBackStackIndices == null) {
mBackStackIndices = new ArrayList<BackStackRecord>();
}
int index = mBackStackIndices.size();
if (DEBUG) Log.v(TAG, "Setting back stack index " + index + " to " + bse);
mBackStackIndices.add(bse);
return index;
} else {
int index = mAvailBackStackIndices.remove(mAvailBackStackIndices.size()-1);
if (DEBUG) Log.v(TAG, "Adding back stack index " + index + " with " + bse);
mBackStackIndices.set(index, bse);
return index;
}
}
}
synchronized (this) {
if (mBackStackIndices == null) {
mBackStackIndices = new ArrayList<BackStackRecord>();
}
int N = mBackStackIndices.size();
if (index < N) {
if (DEBUG) Log.v(TAG, "Setting back stack index " + index + " to " + bse);
mBackStackIndices.set(index, bse);
} else {
while (N < index) {
mBackStackIndices.add(null);
if (mAvailBackStackIndices == null) {
mAvailBackStackIndices = new ArrayList<Integer>();
}
if (DEBUG) Log.v(TAG, "Adding available back stack index " + N);
mAvailBackStackIndices.add(N);
N++;
}
if (DEBUG) Log.v(TAG, "Adding back stack index " + index + " with " + bse);
mBackStackIndices.add(bse);
}
}
}
synchronized (this) {
mBackStackIndices.set(index, null);
if (mAvailBackStackIndices == null) {
mAvailBackStackIndices = new ArrayList<Integer>();
}
if (DEBUG) Log.v(TAG, "Freeing back stack index " + index);
mAvailBackStackIndices.add(index);
}
}
if (mExecutingActions) {
throw new IllegalStateException("Recursive entry to executePendingTransactions");
}
if (Looper.myLooper() != mActivity.mHandler.getLooper()) {
throw new IllegalStateException("Must be called from main thread of process");
}
boolean didSomething = false;
while (true) {
int numActions;
synchronized (this) {
if (mPendingActions == null || mPendingActions.size() == 0) {
break;
}
numActions = mPendingActions.size();
if (mTmpActions == null || mTmpActions.length < numActions) {
mTmpActions = new Runnable[numActions];
}
mPendingActions.toArray(mTmpActions);
mPendingActions.clear();
mActivity.mHandler.removeCallbacks(mExecCommit);
}
mExecutingActions = true;
for (int i=0; i<numActions; i++) {
mTmpActions[i].run();
mTmpActions[i] = null;
}
mExecutingActions = false;
didSomething = true;
}
if (mHavePendingDeferredStart) {
boolean loadersRunning = false;
for (int i=0; i<mActive.size(); i++) {
Fragment f = mActive.get(i);
if (f != null && f.mLoaderManager != null) {
loadersRunning |= f.mLoaderManager.hasRunningLoaders();
}
}
if (!loadersRunning) {
mHavePendingDeferredStart = false;
startPendingDeferredFragments();
}
}
return didSomething;
}
if (mBackStackChangeListeners != null) {
for (int i=0; i<mBackStackChangeListeners.size(); i++) {
mBackStackChangeListeners.get(i).onBackStackChanged();
}
}
}
if (mBackStack == null) {
mBackStack = new ArrayList<BackStackRecord>();
}
mBackStack.add(state);
reportBackStackChanged();
}
if (mBackStack == null) {
return false;
}
if (name == null && id < 0 && (flags&POP_BACK_STACK_INCLUSIVE) == 0) {
int last = mBackStack.size()-1;
if (last < 0) {
return false;
}
final BackStackRecord bss = mBackStack.remove(last);
bss.popFromBackStack(true);
reportBackStackChanged();
} else {
int index = -1;
if (name != null || id >= 0) {
index = mBackStack.size()-1;
while (index >= 0) {
BackStackRecord bss = mBackStack.get(index);
if (name != null && name.equals(bss.getName())) {
break;
}
if (id >= 0 && id == bss.mIndex) {
break;
}
index--;
}
if (index < 0) {
return false;
}
if ((flags&POP_BACK_STACK_INCLUSIVE) != 0) {
index--;
while (index >= 0) {
BackStackRecord bss = mBackStack.get(index);
if ((name != null && name.equals(bss.getName()))
|| (id >= 0 && id == bss.mIndex)) {
index--;
continue;
}
break;
}
}
}
if (index == mBackStack.size()-1) {
return false;
}
final ArrayList<BackStackRecord> states
= new ArrayList<BackStackRecord>();
for (int i=mBackStack.size()-1; i>index; i--) {
states.add(mBackStack.remove(i));
}
final int LAST = states.size()-1;
for (int i=0; i<=LAST; i++) {
if (DEBUG) Log.v(TAG, "Popping back stack state: " + states.get(i));
states.get(i).popFromBackStack(i == LAST);
}
reportBackStackChanged();
}
return true;
}
ArrayList<Fragment> fragments = null;
if (mActive != null) {
for (int i=0; i<mActive.size(); i++) {
Fragment f = mActive.get(i);
if (f != null && f.mRetainInstance) {
if (fragments == null) {
fragments = new ArrayList<Fragment>();
}
fragments.add(f);
f.mRetaining = true;
f.mTargetIndex = f.mTarget != null ? f.mTarget.mIndex : -1;
}
}
}
return fragments;
}
if (f.mInnerView == null) {
return;
}
if (mStateArray == null) {
mStateArray = new SparseArray<Parcelable>();
} else {
mStateArray.clear();
}
f.mInnerView.saveHierarchyState(mStateArray);
if (mStateArray.size() > 0) {
f.mSavedViewState = mStateArray;
mStateArray = null;
}
}
Bundle result = null;
if (mStateBundle == null) {
mStateBundle = new Bundle();
}
f.onSaveInstanceState(mStateBundle);
if (!mStateBundle.isEmpty()) {
result = mStateBundle;
mStateBundle = null;
}
if (f.mView != null) {
saveFragmentViewState(f);
}
if (f.mSavedViewState != null) {
if (result == null) {
result = new Bundle();
}
result.putSparseParcelableArray(
FragmentManagerImpl.VIEW_STATE_TAG, f.mSavedViewState);
}
if (!f.mUserVisibleHint) {
if (result == null) {
result = new Bundle();
}
result.putBoolean(FragmentManagerImpl.USER_VISIBLE_HINT_TAG, f.mUserVisibleHint);
}
return result;
}
execPendingActions();
if (HONEYCOMB) {
mStateSaved = true;
}
if (mActive == null || mActive.size() <= 0) {
return null;
}
int N = mActive.size();
FragmentState[] active = new FragmentState[N];
boolean haveFragments = false;
for (int i=0; i<N; i++) {
Fragment f = mActive.get(i);
if (f != null) {
haveFragments = true;
FragmentState fs = new FragmentState(f);
active[i] = fs;
if (f.mState > Fragment.INITIALIZING && fs.mSavedFragmentState == null) {
fs.mSavedFragmentState = saveFragmentBasicState(f);
if (f.mTarget != null) {
if (f.mTarget.mIndex < 0) {
String msg = "Failure saving state: " + f
+ " has target not in fragment manager: " + f.mTarget;
Log.e(TAG, msg);
dump(" ", null, new PrintWriter(new LogWriter(TAG)), new String[] { });
throw new IllegalStateException(msg);
}
if (fs.mSavedFragmentState == null) {
fs.mSavedFragmentState = new Bundle();
}
putFragment(fs.mSavedFragmentState,
FragmentManagerImpl.TARGET_STATE_TAG, f.mTarget);
if (f.mTargetRequestCode != 0) {
fs.mSavedFragmentState.putInt(
FragmentManagerImpl.TARGET_REQUEST_CODE_STATE_TAG,
f.mTargetRequestCode);
}
}
} else {
fs.mSavedFragmentState = f.mSavedFragmentState;
}
if (DEBUG) Log.v(TAG, "Saved state of " + f + ": "
+ fs.mSavedFragmentState);
}
}
if (!haveFragments) {
if (DEBUG) Log.v(TAG, "saveAllState: no fragments!");
return null;
}
int[] added = null;
BackStackState[] backStack = null;
if (mAdded != null) {
N = mAdded.size();
if (N > 0) {
added = new int[N];
for (int i=0; i<N; i++) {
added[i] = mAdded.get(i).mIndex;
if (DEBUG) Log.v(TAG, "saveAllState: adding fragment #" + i
+ ": " + mAdded.get(i));
}
}
}
if (mBackStack != null) {
N = mBackStack.size();
if (N > 0) {
backStack = new BackStackState[N];
for (int i=0; i<N; i++) {
backStack[i] = new BackStackState(this, mBackStack.get(i));
if (DEBUG) Log.v(TAG, "saveAllState: adding back stack #" + i
+ ": " + mBackStack.get(i));
}
}
}
FragmentManagerState fms = new FragmentManagerState();
fms.mActive = active;
fms.mAdded = added;
fms.mBackStack = backStack;
return fms;
}
if (state == null) return;
FragmentManagerState fms = (FragmentManagerState)state;
if (fms.mActive == null) return;
if (nonConfig != null) {
for (int i=0; i<nonConfig.size(); i++) {
Fragment f = nonConfig.get(i);
if (DEBUG) Log.v(TAG, "restoreAllState: re-attaching retained " + f);
FragmentState fs = fms.mActive[f.mIndex];
fs.mInstance = f;
f.mSavedViewState = null;
f.mBackStackNesting = 0;
f.mInLayout = false;
f.mAdded = false;
f.mTarget = null;
if (fs.mSavedFragmentState != null) {
fs.mSavedFragmentState.setClassLoader(mActivity.getClassLoader());
f.mSavedViewState = fs.mSavedFragmentState.getSparseParcelableArray(
FragmentManagerImpl.VIEW_STATE_TAG);
}
}
}
mActive = new ArrayList<Fragment>(fms.mActive.length);
if (mAvailIndices != null) {
mAvailIndices.clear();
}
for (int i=0; i<fms.mActive.length; i++) {
FragmentState fs = fms.mActive[i];
if (fs != null) {
Fragment f = fs.instantiate(mActivity);
if (DEBUG) Log.v(TAG, "restoreAllState: adding #" + i + ": " + f);
mActive.add(f);
fs.mInstance = null;
} else {
if (DEBUG) Log.v(TAG, "restoreAllState: adding #" + i + ": (null)");
mActive.add(null);
if (mAvailIndices == null) {
mAvailIndices = new ArrayList<Integer>();
}
if (DEBUG) Log.v(TAG, "restoreAllState: adding avail #" + i);
mAvailIndices.add(i);
}
}
if (nonConfig != null) {
for (int i=0; i<nonConfig.size(); i++) {
Fragment f = nonConfig.get(i);
if (f.mTargetIndex >= 0) {
if (f.mTargetIndex < mActive.size()) {
f.mTarget = mActive.get(f.mTargetIndex);
} else {
Log.w(TAG, "Re-attaching retained fragment " + f
+ " target no longer exists: " + f.mTargetIndex);
f.mTarget = null;
}
}
}
}
if (fms.mAdded != null) {
mAdded = new ArrayList<Fragment>(fms.mAdded.length);
for (int i=0; i<fms.mAdded.length; i++) {
Fragment f = mActive.get(fms.mAdded[i]);
if (f == null) {
throw new IllegalStateException(
"No instantiated fragment for index #" + fms.mAdded[i]);
}
f.mAdded = true;
if (DEBUG) Log.v(TAG, "restoreAllState: making added #" + i + ": " + f);
mAdded.add(f);
}
} else {
mAdded = null;
}
if (fms.mBackStack != null) {
mBackStack = new ArrayList<BackStackRecord>(fms.mBackStack.length);
for (int i=0; i<fms.mBackStack.length; i++) {
BackStackRecord bse = fms.mBackStack[i].instantiate(this);
if (DEBUG) Log.v(TAG, "restoreAllState: adding bse #" + i
+ " (index " + bse.mIndex + "): " + bse);
mBackStack.add(bse);
if (bse.mIndex >= 0) {
setBackStackIndex(bse.mIndex, bse);
}
}
} else {
mBackStack = null;
}
}
if (mActivity != null) throw new IllegalStateException();
mActivity = activity;
}
mStateSaved = false;
}
mStateSaved = false;
moveToState(Fragment.CREATED, false);
}
mStateSaved = false;
moveToState(Fragment.ACTIVITY_CREATED, false);
}
mStateSaved = false;
moveToState(Fragment.STARTED, false);
}
mStateSaved = false;
moveToState(Fragment.RESUMED, false);
}
moveToState(Fragment.STARTED, false);
}
mStateSaved = true;
moveToState(Fragment.STOPPED, false);
}
moveToState(Fragment.ACTIVITY_CREATED, false);
}
mDestroyed = true;
execPendingActions();
moveToState(Fragment.INITIALIZING, false);
mActivity = null;
}
if (mActive != null) {
for (int i=0; i<mAdded.size(); i++) {
Fragment f = mAdded.get(i);
if (f != null) {
f.onConfigurationChanged(newConfig);
}
}
}
}
if (mActive != null) {
for (int i=0; i<mAdded.size(); i++) {
Fragment f = mAdded.get(i);
if (f != null) {
f.onLowMemory();
}
}
}
}
public boolean (Menu menu, MenuInflater inflater) {
boolean show = false;
ArrayList<Fragment> newMenus = null;
if (mActive != null) {
for (int i=0; i<mAdded.size(); i++) {
Fragment f = mAdded.get(i);
if (f != null && !f.mHidden && f.mHasMenu && f.mMenuVisible) {
show = true;
f.onCreateOptionsMenu(menu, inflater);
if (newMenus == null) {
newMenus = new ArrayList<Fragment>();
}
newMenus.add(f);
}
}
}
if (mCreatedMenus != null) {
for (int i=0; i<mCreatedMenus.size(); i++) {
Fragment f = mCreatedMenus.get(i);
if (newMenus == null || !newMenus.contains(f)) {
f.onDestroyOptionsMenu();
}
}
}
mCreatedMenus = newMenus;
return show;
}
public boolean (Menu menu) {
boolean show = false;
if (mActive != null) {
for (int i=0; i<mAdded.size(); i++) {
Fragment f = mAdded.get(i);
if (f != null && !f.mHidden && f.mHasMenu && f.mMenuVisible) {
show = true;
f.onPrepareOptionsMenu(menu);
}
}
}
return show;
}
public boolean (MenuItem item) {
if (mActive != null) {
for (int i=0; i<mAdded.size(); i++) {
Fragment f = mAdded.get(i);
if (f != null && !f.mHidden && f.mHasMenu && f.mMenuVisible) {
if (f.onOptionsItemSelected(item)) {
return true;
}
}
}
}
return false;
}
if (mActive != null) {
for (int i=0; i<mAdded.size(); i++) {
Fragment f = mAdded.get(i);
if (f != null && !f.mHidden) {
if (f.onContextItemSelected(item)) {
return true;
}
}
}
}
return false;
}
public void (Menu menu) {
if (mActive != null) {
for (int i=0; i<mAdded.size(); i++) {
Fragment f = mAdded.get(i);
if (f != null && !f.mHidden && f.mHasMenu && f.mMenuVisible) {
f.onOptionsMenuClosed(menu);
}
}
}
}
int rev = 0;
switch (transit) {
case FragmentTransaction.TRANSIT_FRAGMENT_OPEN:
rev = FragmentTransaction.TRANSIT_FRAGMENT_CLOSE;
break;
case FragmentTransaction.TRANSIT_FRAGMENT_CLOSE:
rev = FragmentTransaction.TRANSIT_FRAGMENT_OPEN;
break;
case FragmentTransaction.TRANSIT_FRAGMENT_FADE:
rev = FragmentTransaction.TRANSIT_FRAGMENT_FADE;
break;
}
return rev;
}
public static final int ANIM_STYLE_OPEN_ENTER = 1;
public static final int ANIM_STYLE_OPEN_EXIT = 2;
public static final int ANIM_STYLE_CLOSE_ENTER = 3;
public static final int ANIM_STYLE_CLOSE_EXIT = 4;
public static final int ANIM_STYLE_FADE_ENTER = 5;
public static final int ANIM_STYLE_FADE_EXIT = 6;
int animAttr = -1;
switch (transit) {
case FragmentTransaction.TRANSIT_FRAGMENT_OPEN:
animAttr = enter ? ANIM_STYLE_OPEN_ENTER : ANIM_STYLE_OPEN_EXIT;
break;
case FragmentTransaction.TRANSIT_FRAGMENT_CLOSE:
animAttr = enter ? ANIM_STYLE_CLOSE_ENTER : ANIM_STYLE_CLOSE_EXIT;
break;
case FragmentTransaction.TRANSIT_FRAGMENT_FADE:
animAttr = enter ? ANIM_STYLE_FADE_ENTER : ANIM_STYLE_FADE_EXIT;
break;
}
return animAttr;
}
}