X-Git-Url: https://notaz.gp2x.de/cgi-bin/gitweb.cgi?a=blobdiff_plain;ds=sidebyside;f=apps%2FAndroidSupportV2%2Fsrc%2Fandroid%2Fsupport%2Fv2%2Fapp%2FFragmentManager.java;fp=apps%2FAndroidSupportV2%2Fsrc%2Fandroid%2Fsupport%2Fv2%2Fapp%2FFragmentManager.java;h=0000000000000000000000000000000000000000;hb=86591c820f761cc27e31f78790c5a447b8411a33;hp=35558f1b9d5a850ee81909f0d8ec899b9760ff73;hpb=ebcf0cf7399e3ec5ba51c5a904553fbcc55725e5;p=android_pandora.git diff --git a/apps/AndroidSupportV2/src/android/support/v2/app/FragmentManager.java b/apps/AndroidSupportV2/src/android/support/v2/app/FragmentManager.java deleted file mode 100644 index 35558f1..0000000 --- a/apps/AndroidSupportV2/src/android/support/v2/app/FragmentManager.java +++ /dev/null @@ -1,1829 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * 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 android.support.v2.app; - -import android.R; -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.v2.util.DebugUtils; -import android.support.v2.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.Menu; -import android.view.MenuInflater; -import android.view.MenuItem; -import android.view.View; -import android.view.ViewGroup; - -import java.io.FileDescriptor; -import java.io.PrintWriter; -import java.util.ArrayList; -import java.util.Arrays; - -/** - * Static library support version of the framework's {@link android.app.FragmentManager}. - * Used to write apps that run on platforms prior to Android 3.0. When running - * on Android 3.0 or above, this implementation is still used; it does not try - * to switch to the framework's implementation. See the framework SDK - * documentation for a class overview. - * - *

Your activity must derive from {@link FragmentActivity} to use this. - */ -public abstract class FragmentManager { - /** - * Representation of an entry on the fragment back stack, as created - * with {@link FragmentTransaction#addToBackStack(String) - * FragmentTransaction.addToBackStack()}. Entries can later be - * retrieved with {@link FragmentManager#getBackStackEntryAt(int) - * FragmentManager.getBackStackEntry()}. - * - *

Note that you should never hold on to a BackStackEntry object; - * the identifier as returned by {@link #getId} is the only thing that - * will be persisted across activity instances. - */ - public interface BackStackEntry { - /** - * Return the unique identifier for the entry. This is the only - * representation of the entry that will persist across activity - * instances. - */ - public int getId(); - - /** - * Return the full bread crumb title resource identifier for the entry, - * or 0 if it does not have one. - */ - public int getBreadCrumbTitleRes(); - - /** - * Return the short bread crumb title resource identifier for the entry, - * or 0 if it does not have one. - */ - public int getBreadCrumbShortTitleRes(); - - /** - * Return the full bread crumb title for the entry, or null if it - * does not have one. - */ - public CharSequence getBreadCrumbTitle(); - - /** - * Return the short bread crumb title for the entry, or null if it - * does not have one. - */ - public CharSequence getBreadCrumbShortTitle(); - } - - /** - * Interface to watch for changes to the back stack. - */ - public interface OnBackStackChangedListener { - /** - * Called whenever the contents of the back stack change. - */ - public void onBackStackChanged(); - } - - /** - * Start a series of edit operations on the Fragments associated with - * this FragmentManager. - * - *

Note: A fragment transaction can only be created/committed prior - * to an activity saving its state. If you try to commit a transaction - * after {@link FragmentActivity#onSaveInstanceState FragmentActivity.onSaveInstanceState()} - * (and prior to a following {@link FragmentActivity#onStart FragmentActivity.onStart} - * or {@link FragmentActivity#onResume FragmentActivity.onResume()}, you will get an error. - * This is because the framework takes care of saving your current fragments - * in the state, and if changes are made after the state is saved then they - * will be lost.

- */ - public abstract FragmentTransaction beginTransaction(); - - /** @hide -- remove once prebuilts are in. */ - @Deprecated - public FragmentTransaction openTransaction() { - return beginTransaction(); - } - - /** - * After a {@link FragmentTransaction} is committed with - * {@link FragmentTransaction#commit FragmentTransaction.commit()}, it - * is scheduled to be executed asynchronously on the process's main thread. - * If you want to immediately executing any such pending operations, you - * can call this function (only from the main thread) to do so. Note that - * all callbacks and other related behavior will be done from within this - * call, so be careful about where this is called from. - * - * @return Returns true if there were any pending transactions to be - * executed. - */ - public abstract boolean executePendingTransactions(); - - /** - * Finds a fragment that was identified by the given id either when inflated - * from XML or as the container ID when added in a transaction. This first - * searches through fragments that are currently added to the manager's - * activity; if no such fragment is found, then all fragments currently - * on the back stack associated with this ID are searched. - * @return The fragment if found or null otherwise. - */ - public abstract Fragment findFragmentById(int id); - - /** - * Finds a fragment that was identified by the given tag either when inflated - * from XML or as supplied when added in a transaction. This first - * searches through fragments that are currently added to the manager's - * activity; if no such fragment is found, then all fragments currently - * on the back stack are searched. - * @return The fragment if found or null otherwise. - */ - public abstract Fragment findFragmentByTag(String tag); - - /** - * Flag for {@link #popBackStack(String, int)} - * and {@link #popBackStack(int, int)}: If set, and the name or ID of - * a back stack entry has been supplied, then all matching entries will - * be consumed until one that doesn't match is found or the bottom of - * the stack is reached. Otherwise, all entries up to but not including that entry - * will be removed. - */ - public static final int POP_BACK_STACK_INCLUSIVE = 1<<0; - - /** - * Pop the top state off the back stack. Returns true if there was one - * to pop, else false. This function is asynchronous -- it enqueues the - * request to pop, but the action will not be performed until the application - * returns to its event loop. - */ - public abstract void popBackStack(); - - /** - * Like {@link #popBackStack()}, but performs the operation immediately - * inside of the call. This is like calling {@link #executePendingTransactions()} - * afterwards. - * @return Returns true if there was something popped, else false. - */ - public abstract boolean popBackStackImmediate(); - - /** - * Pop the last fragment transition from the manager's fragment - * back stack. If there is nothing to pop, false is returned. - * This function is asynchronous -- it enqueues the - * request to pop, but the action will not be performed until the application - * returns to its event loop. - * - * @param name If non-null, this is the name of a previous back state - * to look for; if found, all states up to that state will be popped. The - * {@link #POP_BACK_STACK_INCLUSIVE} flag can be used to control whether - * the named state itself is popped. If null, only the top state is popped. - * @param flags Either 0 or {@link #POP_BACK_STACK_INCLUSIVE}. - */ - public abstract void popBackStack(String name, int flags); - - /** - * Like {@link #popBackStack(String, int)}, but performs the operation immediately - * inside of the call. This is like calling {@link #executePendingTransactions()} - * afterwards. - * @return Returns true if there was something popped, else false. - */ - public abstract boolean popBackStackImmediate(String name, int flags); - - /** - * Pop all back stack states up to the one with the given identifier. - * This function is asynchronous -- it enqueues the - * request to pop, but the action will not be performed until the application - * returns to its event loop. - * - * @param id Identifier of the stated to be popped. If no identifier exists, - * false is returned. - * The identifier is the number returned by - * {@link FragmentTransaction#commit() FragmentTransaction.commit()}. The - * {@link #POP_BACK_STACK_INCLUSIVE} flag can be used to control whether - * the named state itself is popped. - * @param flags Either 0 or {@link #POP_BACK_STACK_INCLUSIVE}. - */ - public abstract void popBackStack(int id, int flags); - - /** - * Like {@link #popBackStack(int, int)}, but performs the operation immediately - * inside of the call. This is like calling {@link #executePendingTransactions()} - * afterwards. - * @return Returns true if there was something popped, else false. - */ - public abstract boolean popBackStackImmediate(int id, int flags); - - /** - * Return the number of entries currently in the back stack. - */ - public abstract int getBackStackEntryCount(); - - /** - * Return the BackStackEntry at index index in the back stack; - * entries start index 0 being the bottom of the stack. - */ - public abstract BackStackEntry getBackStackEntryAt(int index); - - /** - * Add a new listener for changes to the fragment back stack. - */ - public abstract void addOnBackStackChangedListener(OnBackStackChangedListener listener); - - /** - * Remove a listener that was previously added with - * {@link #addOnBackStackChangedListener(OnBackStackChangedListener)}. - */ - public abstract void removeOnBackStackChangedListener(OnBackStackChangedListener listener); - - /** - * Put a reference to a fragment in a Bundle. This Bundle can be - * persisted as saved state, and when later restoring - * {@link #getFragment(Bundle, String)} will return the current - * instance of the same fragment. - * - * @param bundle The bundle in which to put the fragment reference. - * @param key The name of the entry in the bundle. - * @param fragment The Fragment whose reference is to be stored. - */ - public abstract void putFragment(Bundle bundle, String key, Fragment fragment); - - /** - * Retrieve the current Fragment instance for a reference previously - * placed with {@link #putFragment(Bundle, String, Fragment)}. - * - * @param bundle The bundle from which to retrieve the fragment reference. - * @param key The name of the entry in the bundle. - * @return Returns the current Fragment instance that is associated with - * the given reference. - */ - public abstract Fragment getFragment(Bundle bundle, String key); - - /** - * Print the FragmentManager's state into the given stream. - * - * @param prefix Text to print at the front of each line. - * @param fd The raw file descriptor that the dump is being sent to. - * @param writer A PrintWriter to which the dump is to be set. - * @param args Additional arguments to the dump request. - */ - public abstract void dump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args); - - /** - * Control whether the framework's internal fragment manager debugging - * logs are turned on. If enabled, you will see output in logcat as - * the framework performs fragment operations. - */ - public static void enableDebugLogging(boolean enabled) { - FragmentManagerImpl.DEBUG = enabled; - } -} - -final class FragmentManagerState implements Parcelable { - FragmentState[] mActive; - int[] mAdded; - BackStackState[] mBackStack; - - public FragmentManagerState() { - } - - public FragmentManagerState(Parcel in) { - mActive = in.createTypedArray(FragmentState.CREATOR); - mAdded = in.createIntArray(); - mBackStack = in.createTypedArray(BackStackState.CREATOR); - } - - public int describeContents() { - return 0; - } - - public void writeToParcel(Parcel dest, int flags) { - dest.writeTypedArray(mActive, flags); - dest.writeIntArray(mAdded); - dest.writeTypedArray(mBackStack, flags); - } - - public static final Parcelable.Creator CREATOR - = new Parcelable.Creator() { - public FragmentManagerState createFromParcel(Parcel in) { - return new FragmentManagerState(in); - } - - public FragmentManagerState[] newArray(int size) { - return new FragmentManagerState[size]; - } - }; -} - -/** - * Container for fragments associated with an activity. - */ -final class FragmentManagerImpl extends FragmentManager { - static boolean DEBUG = false; - static final String TAG = "FragmentManager"; - - //v4 static final boolean HONEYCOMB = android.os.Build.VERSION.SDK_INT >= 11; - static final boolean HONEYCOMB = android.support.v2.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"; - - ArrayList mPendingActions; - Runnable[] mTmpActions; - boolean mExecutingActions; - - ArrayList mActive; - ArrayList mAdded; - ArrayList mAvailIndices; - ArrayList mBackStack; - ArrayList mCreatedMenus; - - // Must be accessed while locked. - ArrayList mBackStackIndices; - ArrayList mAvailBackStackIndices; - - ArrayList mBackStackChangeListeners; - - int mCurState = Fragment.INITIALIZING; - FragmentActivity mActivity; - - boolean mNeedMenuInvalidate; - boolean mStateSaved; - boolean mDestroyed; - String mNoTransactionsBecause; - - // Temporary vars for state save and restore. - Bundle mStateBundle = null; - SparseArray mStateArray = null; - - Runnable mExecCommit = new Runnable() { - @Override - public void run() { - execPendingActions(); - } - }; - - @Override - public FragmentTransaction beginTransaction() { - return new BackStackRecord(this); - } - - @Override - public boolean executePendingTransactions() { - return execPendingActions(); - } - - @Override - public void popBackStack() { - enqueueAction(new Runnable() { - @Override public void run() { - popBackStackState(mActivity.mHandler, null, -1, 0); - } - }, false); - } - - @Override - public boolean popBackStackImmediate() { - 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 - public boolean popBackStackImmediate(String name, int flags) { - checkStateLoss(); - executePendingTransactions(); - return popBackStackState(mActivity.mHandler, name, -1, flags); - } - - @Override - public void popBackStack(final int id, final int flags) { - if (id < 0) { - throw new IllegalArgumentException("Bad id: " + id); - } - enqueueAction(new Runnable() { - @Override public void run() { - popBackStackState(mActivity.mHandler, null, id, flags); - } - }, false); - } - - @Override - public boolean popBackStackImmediate(int id, int flags) { - checkStateLoss(); - executePendingTransactions(); - if (id < 0) { - throw new IllegalArgumentException("Bad id: " + id); - } - return popBackStackState(mActivity.mHandler, null, id, flags); - } - - @Override - public int getBackStackEntryCount() { - return mBackStack != null ? mBackStack.size() : 0; - } - - @Override - public BackStackEntry getBackStackEntryAt(int index) { - return mBackStack.get(index); - } - - @Override - public void addOnBackStackChangedListener(OnBackStackChangedListener listener) { - if (mBackStackChangeListeners == null) { - mBackStackChangeListeners = new ArrayList(); - } - mBackStackChangeListeners.add(listener); - } - - @Override - public void removeOnBackStackChangedListener(OnBackStackChangedListener listener) { - 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 - public String toString() { - 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 0) { - writer.print(prefix); writer.println("Added Fragments:"); - for (int i=0; i 0) { - writer.print(prefix); writer.println("Fragments Created Menus:"); - for (int i=0; i 0) { - writer.print(prefix); writer.println("Back Stack:"); - for (int i=0; i 0) { - writer.print(prefix); writer.println("Back Stack Indices:"); - for (int i=0; i 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 Fragment.CREATED) { - newState = Fragment.CREATED; - } - - if (f.mState < newState) { - // For fragments that are created from a layout, when restoring from - // state we don't want to allow them to be created until they are - // being reloaded from the layout. - if (f.mFromLayout && !f.mInLayout) { - return; - } - if (f.mAnimatingAway != null) { - // The fragment is currently being animated... but! Now we - // want to move our state back up. Give up on waiting for the - // animation, move to whatever the final state should be once - // the animation is done, and then we can proceed from there. - 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.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) { - // For fragments that are part of the content view - // layout, we need to instantiate the view immediately - // and the inflater will take care of adding it. - 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); - f.restoreViewState(); - if (f.mHidden) f.mView.setVisibility(View.GONE); - } else { - f.mInnerView = null; - } - } - case Fragment.CREATED: - if (newState > Fragment.CREATED) { - if (DEBUG) Log.v(TAG, "moveto CONTENT: " + 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); - f.restoreViewState(); - } - if (f.mHidden) f.mView.setVisibility(View.GONE); - } 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()"); - } - f.mSavedFragmentState = null; - } - case Fragment.ACTIVITY_CREATED: - if (newState > Fragment.ACTIVITY_CREATED) { - if (DEBUG) Log.v(TAG, "moveto STARTED: " + f); - f.mCalled = false; - f.onStart(); - 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()"); - } - } - } - } 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.ACTIVITY_CREATED: - if (newState < Fragment.ACTIVITY_CREATED) { - if (DEBUG) Log.v(TAG, "movefrom CONTENT: " + f); - if (f.mView != null) { - // Need to save the current view state if not - // done already. - if (!mActivity.isFinishing() && f.mSavedViewState == null) { - saveFragmentViewState(f); - } - } - f.mCalled = false; - f.onDestroyView(); - 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 - public void onAnimationEnd(Animation animation) { - if (fragment.mAnimatingAway != null) { - fragment.mAnimatingAway = null; - moveToState(fragment, fragment.mStateAfterAnimating, - 0, 0); - } - } - @Override - public void onAnimationRepeat(Animation animation) { - } - @Override - public void onAnimationStart(Animation animation) { - } - }); - 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) { - // The fragment's containing activity is - // being destroyed, but this fragment is - // currently animating away. Stop the - // animation right now -- it is not needed, - // and we can't wait any more on destroying - // the fragment. - View v = f.mAnimatingAway; - f.mAnimatingAway = null; - v.clearAnimation(); - } - } - if (f.mAnimatingAway != null) { - // We are waiting for the fragment's view to finish - // animating away. Just make a note of the state - // the fragment now should move to once the animation - // is done. - f.mStateAfterAnimating = newState; - } 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()"); - } - f.mImmediateActivity = null; - f.mActivity = null; - f.mFragmentManager = null; - } - } - } - } - - f.mState = newState; - } - - void moveToState(Fragment f) { - moveToState(f, mCurState, 0, 0); - } - - void moveToState(int newState, boolean always) { - 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) { - for (int i=0; i= 0) { - return; - } - - if (mAvailIndices == null || mAvailIndices.size() <= 0) { - if (mActive == null) { - mActive = new ArrayList(); - } - f.setIndex(mActive.size()); - mActive.add(f); - - } else { - f.setIndex(mAvailIndices.remove(mAvailIndices.size()-1)); - mActive.set(f.mIndex, f); - } - } - - void makeInactive(Fragment 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(); - } - mAvailIndices.add(f.mIndex); - mActivity.invalidateSupportFragmentIndex(f.mIndex); - f.clearIndex(); - } - - public void addFragment(Fragment fragment, boolean moveToStateNow) { - if (mAdded == null) { - mAdded = new ArrayList(); - } - mAdded.add(fragment); - makeActive(fragment); - if (DEBUG) Log.v(TAG, "add: " + fragment); - fragment.mAdded = true; - fragment.mRemoving = false; - if (fragment.mHasMenu) { - 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); - mAdded.remove(fragment); - final boolean inactive = fragment.mBackStackNesting <= 0; - if (fragment.mHasMenu) { - mNeedMenuInvalidate = true; - } - fragment.mAdded = false; - fragment.mRemoving = true; - moveToState(fragment, inactive ? Fragment.INITIALIZING : Fragment.CREATED, - transition, transitionStyle); - if (inactive) { - makeInactive(fragment); - } - } - - 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) { - 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) { - mNeedMenuInvalidate = true; - } - fragment.onHiddenChanged(false); - } - } - - public Fragment findFragmentById(int id) { - if (mActive != null) { - // First look through added fragments. - for (int i=mAdded.size()-1; i>=0; i--) { - Fragment f = mAdded.get(i); - if (f != null && f.mFragmentId == id) { - return f; - } - } - // Now for any known fragment. - for (int i=mActive.size()-1; i>=0; i--) { - Fragment f = mActive.get(i); - if (f != null && f.mFragmentId == id) { - return f; - } - } - } - return null; - } - - public Fragment findFragmentByTag(String tag) { - if (mActive != null && tag != null) { - // First look through added fragments. - for (int i=mAdded.size()-1; i>=0; i--) { - Fragment f = mAdded.get(i); - if (f != null && tag.equals(f.mTag)) { - return f; - } - } - // Now for any known fragment. - 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; - } - - public Fragment findFragmentByWho(String who) { - 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; - } - - private void checkStateLoss() { - 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(); - } - mPendingActions.add(action); - if (mPendingActions.size() == 1) { - mActivity.mHandler.removeCallbacks(mExecCommit); - mActivity.mHandler.post(mExecCommit); - } - } - } - - public int allocBackStackIndex(BackStackRecord bse) { - synchronized (this) { - if (mAvailBackStackIndices == null || mAvailBackStackIndices.size() <= 0) { - if (mBackStackIndices == null) { - mBackStackIndices = new ArrayList(); - } - 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; - } - } - } - - public void setBackStackIndex(int index, BackStackRecord bse) { - synchronized (this) { - if (mBackStackIndices == null) { - mBackStackIndices = new ArrayList(); - } - 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(); - } - 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); - } - } - } - - public void freeBackStackIndex(int index) { - synchronized (this) { - mBackStackIndices.set(index, null); - if (mAvailBackStackIndices == null) { - mAvailBackStackIndices = new ArrayList(); - } - if (DEBUG) Log.v(TAG, "Freeing back stack index " + index); - mAvailBackStackIndices.add(index); - } - } - - /** - * Only call from main thread! - */ - public boolean execPendingActions() { - 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) { - return didSomething; - } - - 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(); - } - mBackStack.add(state); - reportBackStackChanged(); - } - - boolean popBackStackState(Handler handler, String name, int id, int flags) { - 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) { - // If a name or ID is specified, look for that place in - // the stack. - 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--; - // Consume all following entries that match. - 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 states - = new ArrayList(); - 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 retainNonConfig() { - ArrayList fragments = null; - if (mActive != null) { - for (int i=0; i(); - } - fragments.add(f); - f.mRetaining = true; - } - } - } - return fragments; - } - - void saveFragmentViewState(Fragment f) { - if (f.mInnerView == null) { - return; - } - if (mStateArray == null) { - mStateArray = new SparseArray(); - } - f.mInnerView.saveHierarchyState(mStateArray); - if (mStateArray.size() > 0) { - f.mSavedViewState = mStateArray; - mStateArray = null; - } - } - - Parcelable saveAllState() { - // Make sure all pending operations have now been executed to get - // our state update-to-date. - execPendingActions(); - - if (HONEYCOMB) { - // As of Honeycomb, we save state after pausing. Prior to that - // it is before pausing. With fragments this is an issue, since - // there are many things you may do after pausing but before - // stopping that change the fragment state. For those older - // devices, we will not at this point say that we have saved - // the state, so we will allow them to continue doing fragment - // transactions. This retains the same semantics as Honeycomb, - // though you do have the risk of losing the very most recent state - // if the process is killed... we'll live with that. - mStateSaved = true; - } - - if (mActive == null || mActive.size() <= 0) { - return null; - } - - // First collect all active fragments. - int N = mActive.size(); - FragmentState[] active = new FragmentState[N]; - boolean haveFragments = false; - for (int i=0; i Fragment.INITIALIZING && fs.mSavedFragmentState == null) { - if (mStateBundle == null) { - mStateBundle = new Bundle(); - } - f.onSaveInstanceState(mStateBundle); - if (!mStateBundle.isEmpty()) { - fs.mSavedFragmentState = mStateBundle; - mStateBundle = null; - } - - if (f.mView != null) { - saveFragmentViewState(f); - if (f.mSavedViewState != null) { - if (fs.mSavedFragmentState == null) { - fs.mSavedFragmentState = new Bundle(); - } - fs.mSavedFragmentState.putSparseParcelableArray( - FragmentManagerImpl.VIEW_STATE_TAG, f.mSavedViewState); - } - } - - 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; - - // Build list of currently added fragments. - if (mAdded != null) { - N = mAdded.size(); - if (N > 0) { - added = new int[N]; - for (int i=0; i 0) { - backStack = new BackStackState[N]; - for (int i=0; i nonConfig) { - // If there is no saved state at all, then there can not be - // any nonConfig fragments either, so that is that. - if (state == null) return; - FragmentManagerState fms = (FragmentManagerState)state; - if (fms.mActive == null) return; - - // First re-attach any non-config instances we are retaining back - // to their saved state, so we don't try to instantiate them again. - if (nonConfig != null) { - for (int i=0; i(fms.mActive.length); - if (mAvailIndices != null) { - mAvailIndices.clear(); - } - for (int i=0; i(); - } - if (DEBUG) Log.v(TAG, "restoreAllState: adding avail #" + i); - mAvailIndices.add(i); - } - } - - // Update the target of all retained fragments. - if (nonConfig != null) { - for (int i=0; i(fms.mAdded.length); - for (int i=0; i(fms.mBackStack.length); - for (int i=0; i= 0) { - setBackStackIndex(bse.mIndex, bse); - } - } - } else { - mBackStack = null; - } - } - - public void attachActivity(FragmentActivity activity) { - if (mActivity != null) throw new IllegalStateException(); - mActivity = activity; - } - - public void noteStateNotSaved() { - mStateSaved = false; - } - - public void dispatchCreate() { - mStateSaved = false; - moveToState(Fragment.CREATED, false); - } - - public void dispatchActivityCreated() { - mStateSaved = false; - moveToState(Fragment.ACTIVITY_CREATED, false); - } - - public void dispatchStart() { - mStateSaved = false; - moveToState(Fragment.STARTED, false); - } - - public void dispatchResume() { - mStateSaved = false; - moveToState(Fragment.RESUMED, false); - } - - public void dispatchPause() { - moveToState(Fragment.STARTED, false); - } - - public void dispatchStop() { - // See saveAllState() for the explanation of this. We do this for - // all platform versions, to keep our behavior more consistent between - // them. - mStateSaved = true; - - moveToState(Fragment.ACTIVITY_CREATED, false); - } - - public void dispatchReallyStop(boolean retaining) { - if (mActive != null) { - for (int i=0; i newMenus = null; - if (mActive != null) { - for (int i=0; i(); - } - newMenus.add(f); - } - } - } - - if (mCreatedMenus != null) { - for (int i=0; i