diff --git a/api/current.txt b/api/current.txt index 4a994271dc007..ee21360c490bc 100644 --- a/api/current.txt +++ b/api/current.txt @@ -3348,6 +3348,7 @@ package android.app { method public final boolean equals(java.lang.Object); method public final android.app.Activity getActivity(); method public final android.os.Bundle getArguments(); + method public final android.app.FragmentManager getChildFragmentManager(); method public final android.app.FragmentManager getFragmentManager(); method public final int getId(); method public android.app.LoaderManager getLoaderManager(); @@ -3399,6 +3400,7 @@ package android.app { method public void onStop(); method public void onTrimMemory(int); method public void onViewCreated(android.view.View, android.os.Bundle); + method public void onViewStateRestored(android.os.Bundle); method public void registerForContextMenu(android.view.View); method public void setArguments(android.os.Bundle); method public void setHasOptionsMenu(boolean); diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java index 99dfccbab273d..05b04dc556623 100644 --- a/core/java/android/app/Activity.java +++ b/core/java/android/app/Activity.java @@ -653,8 +653,9 @@ public class Activity extends ContextThemeWrapper /** Start of user-defined activity results. */ public static final int RESULT_FIRST_USER = 1; + static final String FRAGMENTS_TAG = "android:fragments"; + private static final String WINDOW_HIERARCHY_TAG = "android:viewHierarchyState"; - private static final String FRAGMENTS_TAG = "android:fragments"; private static final String SAVED_DIALOG_IDS_KEY = "android:savedDialogIds"; private static final String SAVED_DIALOGS_TAG = "android:savedDialogs"; private static final String SAVED_DIALOG_KEY_PREFIX = "android:dialog_"; @@ -697,7 +698,7 @@ public class Activity extends ContextThemeWrapper Object activity; HashMap children; ArrayList fragments; - SparseArray loaders; + HashMap loaders; } /* package */ NonConfigurationInstances mLastNonConfigurationInstances; @@ -715,8 +716,14 @@ public class Activity extends ContextThemeWrapper private int mTitleColor = 0; final FragmentManagerImpl mFragments = new FragmentManagerImpl(); + final FragmentContainer mContainer = new FragmentContainer() { + @Override + public View findViewById(int id) { + return Activity.this.findViewById(id); + } + }; - SparseArray mAllLoaderManagers; + HashMap mAllLoaderManagers; LoaderManagerImpl mLoaderManager; private static final class ManagedCursor { @@ -744,6 +751,7 @@ public class Activity extends ContextThemeWrapper protected static final int[] FOCUSED_STATE_SET = {com.android.internal.R.attr.state_focused}; + @SuppressWarnings("unused") private final Object mInstanceTracker = StrictMode.trackActivity(this); private Thread mUiThread; @@ -808,19 +816,19 @@ public class Activity extends ContextThemeWrapper return mLoaderManager; } mCheckedForLoaderManager = true; - mLoaderManager = getLoaderManager(-1, mLoadersStarted, true); + mLoaderManager = getLoaderManager(null, mLoadersStarted, true); return mLoaderManager; } - LoaderManagerImpl getLoaderManager(int index, boolean started, boolean create) { + LoaderManagerImpl getLoaderManager(String who, boolean started, boolean create) { if (mAllLoaderManagers == null) { - mAllLoaderManagers = new SparseArray(); + mAllLoaderManagers = new HashMap(); } - LoaderManagerImpl lm = mAllLoaderManagers.get(index); + LoaderManagerImpl lm = mAllLoaderManagers.get(who); if (lm == null) { if (create) { - lm = new LoaderManagerImpl(this, started); - mAllLoaderManagers.put(index, lm); + lm = new LoaderManagerImpl(who, this, started); + mAllLoaderManagers.put(who, lm); } } else { lm.updateActivity(this); @@ -1025,7 +1033,7 @@ public class Activity extends ContextThemeWrapper if (mLoaderManager != null) { mLoaderManager.doStart(); } else if (!mCheckedForLoaderManager) { - mLoaderManager = getLoaderManager(-1, mLoadersStarted, false); + mLoaderManager = getLoaderManager(null, mLoadersStarted, false); } mCheckedForLoaderManager = true; } @@ -1601,13 +1609,17 @@ public class Activity extends ContextThemeWrapper if (mAllLoaderManagers != null) { // prune out any loader managers that were already stopped and so // have nothing useful to retain. - for (int i=mAllLoaderManagers.size()-1; i>=0; i--) { - LoaderManagerImpl lm = mAllLoaderManagers.valueAt(i); - if (lm.mRetaining) { - retainLoaders = true; - } else { - lm.doDestroy(); - mAllLoaderManagers.removeAt(i); + LoaderManagerImpl loaders[] = new LoaderManagerImpl[mAllLoaderManagers.size()]; + mAllLoaderManagers.values().toArray(loaders); + if (loaders != null) { + for (int i=0; i=0; i--) { - LoaderManagerImpl lm = mAllLoaderManagers.valueAt(i); - lm.finishRetain(); - lm.doReportStart(); + LoaderManagerImpl loaders[] = new LoaderManagerImpl[mAllLoaderManagers.size()]; + mAllLoaderManagers.values().toArray(loaders); + if (loaders != null) { + for (int i=0; i {@link #onActivityCreated} tells the fragment that its activity has * completed its own {@link Activity#onCreate Activity.onCreate()}. + *
  • {@link #onViewStateRestored} tells the fragment that all of the saved + * state of its view hierarchy has been restored. *
  • {@link #onStart} makes the fragment visible to the user (based on its * containing activity being started). *
  • {@link #onResume} makes the fragment interacting with the user (based on its @@ -412,7 +414,13 @@ public class Fragment implements ComponentCallbacks2, OnCreateContextMenuListene // Activity this fragment is attached to. Activity mActivity; - + + // Private fragment manager for child fragments inside of this one. + FragmentManagerImpl mChildFragmentManager; + + // If this Fragment is contained in another Fragment, this is that container. + Fragment mParentFragment; + // The optional identifier for this fragment -- either the container ID if it // was dynamically added to the view hierarchy, or the ID supplied in // layout. @@ -595,16 +603,26 @@ public class Fragment implements ComponentCallbacks2, OnCreateContextMenuListene } } - final void restoreViewState() { + final void restoreViewState(Bundle savedInstanceState) { if (mSavedViewState != null) { mView.restoreHierarchyState(mSavedViewState); mSavedViewState = null; } + mCalled = false; + onViewStateRestored(savedInstanceState); + if (!mCalled) { + throw new SuperNotCalledException("Fragment " + this + + " did not call through to super.onViewStateRestored()"); + } } - final void setIndex(int index) { + final void setIndex(int index, Fragment parent) { mIndex = index; - mWho = "android:fragment:" + mIndex; + if (parent != null) { + mWho = parent.mWho + ":" + mIndex; + } else { + mWho = "android:fragment:" + mIndex; + } } final boolean isInBackStack() { @@ -785,11 +803,34 @@ public class Fragment implements ComponentCallbacks2, OnCreateContextMenuListene * before {@link #getActivity()}, during the time from when the fragment is * placed in a {@link FragmentTransaction} until it is committed and * attached to its activity. + * + *

    If this Fragment is a child of another Fragment, the FragmentManager + * returned here will be the parent's {@link #getChildFragmentManager()}. */ final public FragmentManager getFragmentManager() { return mFragmentManager; } + /** + * Return a private FragmentManager for placing and managing Fragments + * inside of this Fragment. + */ + final public FragmentManager getChildFragmentManager() { + if (mChildFragmentManager == null) { + instantiateChildFragmentManager(); + if (mState >= RESUMED) { + mChildFragmentManager.dispatchResume(); + } else if (mState >= STARTED) { + mChildFragmentManager.dispatchStart(); + } else if (mState >= ACTIVITY_CREATED) { + mChildFragmentManager.dispatchActivityCreated(); + } else if (mState >= CREATED) { + mChildFragmentManager.dispatchCreate(); + } + } + return mChildFragmentManager; + } + /** * Return true if the fragment is currently added to its activity. */ @@ -880,6 +921,10 @@ public class Fragment implements ComponentCallbacks2, OnCreateContextMenuListene * */ public void setRetainInstance(boolean retain) { + if (retain && mParentFragment != null) { + throw new IllegalStateException( + "Can't retain fragements that are nested in other fragments"); + } mRetainInstance = retain; } @@ -961,7 +1006,7 @@ public class Fragment implements ComponentCallbacks2, OnCreateContextMenuListene throw new IllegalStateException("Fragment " + this + " not attached to Activity"); } mCheckedForLoaderManager = true; - mLoaderManager = mActivity.getLoaderManager(mIndex, mLoadersStarted, true); + mLoaderManager = mActivity.getLoaderManager(mWho, mLoadersStarted, true); return mLoaderManager; } @@ -1191,7 +1236,7 @@ public class Fragment implements ComponentCallbacks2, OnCreateContextMenuListene * {@link #setRetainInstance(boolean)} to retain their instance, * as this callback tells the fragment when it is fully associated with * the new activity instance. This is called after {@link #onCreateView} - * and before {@link #onStart()}. + * and before {@link #onViewStateRestored(Bundle)}. * * @param savedInstanceState If the fragment is being re-created from * a previous saved state, this is the state. @@ -1199,7 +1244,22 @@ public class Fragment implements ComponentCallbacks2, OnCreateContextMenuListene public void onActivityCreated(Bundle savedInstanceState) { mCalled = true; } - + + /** + * Called when all saved state has been restored into the view hierarchy + * of the fragment. This can be used to do initialization based on saved + * state that you are letting the view hierarchy track itself, such as + * whether check box widgets are currently checked. This is called + * after {@link #onActivityCreated(Bundle)} and before + * {@link #onStart()}. + * + * @param savedInstanceState If the fragment is being re-created from + * a previous saved state, this is the state. + */ + public void onViewStateRestored(Bundle savedInstanceState) { + mCalled = true; + } + /** * Called when the Fragment is visible to the user. This is generally * tied to {@link Activity#onStart() Activity.onStart} of the containing @@ -1212,7 +1272,7 @@ public class Fragment implements ComponentCallbacks2, OnCreateContextMenuListene mLoadersStarted = true; if (!mCheckedForLoaderManager) { mCheckedForLoaderManager = true; - mLoaderManager = mActivity.getLoaderManager(mIndex, mLoadersStarted, false); + mLoaderManager = mActivity.getLoaderManager(mWho, mLoadersStarted, false); } if (mLoaderManager != null) { mLoaderManager.doStart(); @@ -1305,7 +1365,7 @@ public class Fragment implements ComponentCallbacks2, OnCreateContextMenuListene // + " mLoaderManager=" + mLoaderManager); if (!mCheckedForLoaderManager) { mCheckedForLoaderManager = true; - mLoaderManager = mActivity.getLoaderManager(mIndex, mLoadersStarted, false); + mLoaderManager = mActivity.getLoaderManager(mWho, mLoadersStarted, false); } if (mLoaderManager != null) { mLoaderManager.doDestroy(); @@ -1530,6 +1590,14 @@ public class Fragment implements ComponentCallbacks2, OnCreateContextMenuListene writer.print(prefix); writer.print("mActivity="); writer.println(mActivity); } + if (mChildFragmentManager != null) { + writer.print(prefix); writer.print("mChildFragmentManager="); + writer.println(mChildFragmentManager); + } + if (mParentFragment != null) { + writer.print(prefix); writer.print("mParentFragment="); + writer.println(mParentFragment); + } if (mArguments != null) { writer.print(prefix); writer.print("mArguments="); writer.println(mArguments); } @@ -1564,23 +1632,229 @@ public class Fragment implements ComponentCallbacks2, OnCreateContextMenuListene writer.print(prefix); writer.println("Loader Manager:"); mLoaderManager.dump(prefix + " ", fd, writer, args); } + if (mChildFragmentManager != null) { + writer.print(prefix); writer.println("Child Fragment Manager:"); + mChildFragmentManager.dump(prefix + " ", fd, writer, args); + } + } + + Fragment findFragmentByWho(String who) { + if (who.equals(mWho)) { + return this; + } + if (mChildFragmentManager != null) { + return mChildFragmentManager.findFragmentByWho(who); + } + return null; + } + + void instantiateChildFragmentManager() { + mChildFragmentManager = new FragmentManagerImpl(); + mChildFragmentManager.attachActivity(mActivity, new FragmentContainer() { + @Override + public View findViewById(int id) { + if (mView == null) { + throw new IllegalStateException("Fragment does not have a view"); + } + return mView.findViewById(id); + } + }, this); + } + + void performCreate(Bundle savedInstanceState) { + mCalled = false; + onCreate(savedInstanceState); + if (!mCalled) { + throw new SuperNotCalledException("Fragment " + this + + " did not call through to super.onCreate()"); + } + if (savedInstanceState != null) { + Parcelable p = savedInstanceState.getParcelable(Activity.FRAGMENTS_TAG); + if (p != null) { + if (mChildFragmentManager == null) { + instantiateChildFragmentManager(); + } + mChildFragmentManager.restoreAllState(p, null); + mChildFragmentManager.dispatchCreate(); + } + } + } + + void performActivityCreated(Bundle savedInstanceState) { + mCalled = false; + onActivityCreated(savedInstanceState); + if (!mCalled) { + throw new SuperNotCalledException("Fragment " + this + + " did not call through to super.onActivityCreated()"); + } + if (mChildFragmentManager != null) { + mChildFragmentManager.dispatchActivityCreated(); + } } void performStart() { + if (mChildFragmentManager != null) { + mChildFragmentManager.noteStateNotSaved(); + mChildFragmentManager.execPendingActions(); + } + mCalled = false; onStart(); + if (!mCalled) { + throw new SuperNotCalledException("Fragment " + this + + " did not call through to super.onStart()"); + } + if (mChildFragmentManager != null) { + mChildFragmentManager.dispatchStart(); + } if (mLoaderManager != null) { mLoaderManager.doReportStart(); } } + void performResume() { + if (mChildFragmentManager != null) { + mChildFragmentManager.execPendingActions(); + } + mCalled = false; + onResume(); + if (!mCalled) { + throw new SuperNotCalledException("Fragment " + this + + " did not call through to super.onResume()"); + } + if (mChildFragmentManager != null) { + mChildFragmentManager.dispatchResume(); + mChildFragmentManager.execPendingActions(); + } + } + + void performConfigurationChanged(Configuration newConfig) { + onConfigurationChanged(newConfig); + if (mChildFragmentManager != null) { + mChildFragmentManager.dispatchConfigurationChanged(newConfig); + } + } + + void performLowMemory() { + onLowMemory(); + if (mChildFragmentManager != null) { + mChildFragmentManager.dispatchLowMemory(); + } + } + + void performTrimMemory(int level) { + onTrimMemory(level); + if (mChildFragmentManager != null) { + mChildFragmentManager.dispatchTrimMemory(level); + } + } + + boolean performCreateOptionsMenu(Menu menu, MenuInflater inflater) { + boolean show = false; + if (!mHidden) { + if (mHasMenu && mMenuVisible) { + show = true; + onCreateOptionsMenu(menu, inflater); + } + if (mChildFragmentManager != null) { + show |= mChildFragmentManager.dispatchCreateOptionsMenu(menu, inflater); + } + } + return show; + } + + boolean performPrepareOptionsMenu(Menu menu) { + boolean show = false; + if (!mHidden) { + if (mHasMenu && mMenuVisible) { + show = true; + onPrepareOptionsMenu(menu); + } + if (mChildFragmentManager != null) { + show |= mChildFragmentManager.dispatchPrepareOptionsMenu(menu); + } + } + return show; + } + + boolean performOptionsItemSelected(MenuItem item) { + if (!mHidden) { + if (mHasMenu && mMenuVisible) { + if (onOptionsItemSelected(item)) { + return true; + } + } + if (mChildFragmentManager != null) { + if (mChildFragmentManager.dispatchOptionsItemSelected(item)) { + return true; + } + } + } + return false; + } + + boolean performContextItemSelected(MenuItem item) { + if (!mHidden) { + if (onContextItemSelected(item)) { + return true; + } + if (mChildFragmentManager != null) { + if (mChildFragmentManager.dispatchContextItemSelected(item)) { + return true; + } + } + } + return false; + } + + void performOptionsMenuClosed(Menu menu) { + if (!mHidden) { + if (mHasMenu && mMenuVisible) { + onOptionsMenuClosed(menu); + } + if (mChildFragmentManager != null) { + mChildFragmentManager.dispatchOptionsMenuClosed(menu); + } + } + } + + void performSaveInstanceState(Bundle outState) { + onSaveInstanceState(outState); + if (mChildFragmentManager != null) { + Parcelable p = mChildFragmentManager.saveAllState(); + if (p != null) { + outState.putParcelable(Activity.FRAGMENTS_TAG, p); + } + } + } + + void performPause() { + if (mChildFragmentManager != null) { + mChildFragmentManager.dispatchPause(); + } + mCalled = false; + onPause(); + if (!mCalled) { + throw new SuperNotCalledException("Fragment " + this + + " did not call through to super.onPause()"); + } + } + void performStop() { + if (mChildFragmentManager != null) { + mChildFragmentManager.dispatchStop(); + } + mCalled = false; onStop(); + if (!mCalled) { + throw new SuperNotCalledException("Fragment " + this + + " did not call through to super.onStop()"); + } if (mLoadersStarted) { mLoadersStarted = false; if (!mCheckedForLoaderManager) { mCheckedForLoaderManager = true; - mLoaderManager = mActivity.getLoaderManager(mIndex, mLoadersStarted, false); + mLoaderManager = mActivity.getLoaderManager(mWho, mLoadersStarted, false); } if (mLoaderManager != null) { if (mActivity == null || !mActivity.mChangingConfigurations) { @@ -1593,9 +1867,29 @@ public class Fragment implements ComponentCallbacks2, OnCreateContextMenuListene } void performDestroyView() { + if (mChildFragmentManager != null) { + mChildFragmentManager.dispatchDestroyView(); + } + mCalled = false; onDestroyView(); + if (!mCalled) { + throw new SuperNotCalledException("Fragment " + this + + " did not call through to super.onDestroyView()"); + } if (mLoaderManager != null) { mLoaderManager.doReportNextStart(); } } + + void performDestroy() { + if (mChildFragmentManager != null) { + mChildFragmentManager.dispatchDestroy(); + } + mCalled = false; + onDestroy(); + if (!mCalled) { + throw new SuperNotCalledException("Fragment " + this + + " did not call through to super.onDestroy()"); + } + } } diff --git a/core/java/android/app/FragmentManager.java b/core/java/android/app/FragmentManager.java index 52a655700af00..eaaf0d773adc6 100644 --- a/core/java/android/app/FragmentManager.java +++ b/core/java/android/app/FragmentManager.java @@ -20,7 +20,6 @@ import android.animation.Animator; import android.animation.AnimatorInflater; import android.animation.AnimatorListenerAdapter; import android.content.res.Configuration; -import android.content.res.Resources; import android.content.res.TypedArray; import android.os.Bundle; import android.os.Handler; @@ -30,7 +29,6 @@ import android.os.Parcelable; import android.util.DebugUtils; import android.util.Log; import android.util.LogWriter; -import android.util.Slog; import android.util.SparseArray; import android.view.Menu; import android.view.MenuInflater; @@ -380,6 +378,13 @@ final class FragmentManagerState implements Parcelable { }; } +/** + * Callbacks from FragmentManagerImpl to its container. + */ +interface FragmentContainer { + public View findViewById(int id); +} + /** * Container for fragments associated with an activity. */ @@ -410,6 +415,8 @@ final class FragmentManagerImpl extends FragmentManager { int mCurState = Fragment.INITIALIZING; Activity mActivity; + FragmentContainer mContainer; + Fragment mParent; boolean mNeedMenuInvalidate; boolean mStateSaved; @@ -585,7 +592,11 @@ final class FragmentManagerImpl extends FragmentManager { sb.append("FragmentManager{"); sb.append(Integer.toHexString(System.identityHashCode(this))); sb.append(" in "); - DebugUtils.buildShortClassTag(mActivity, sb); + if (mParent != null) { + DebugUtils.buildShortClassTag(mParent, sb); + } else { + DebugUtils.buildShortClassTag(mActivity, sb); + } sb.append("}}"); return sb.toString(); } @@ -681,6 +692,11 @@ final class FragmentManagerImpl extends FragmentManager { } writer.print(prefix); writer.println("FragmentManager misc state:"); + writer.print(prefix); writer.print(" mActivity="); writer.println(mActivity); + writer.print(prefix); writer.print(" mContainer="); writer.println(mContainer); + if (mParent != null) { + writer.print(prefix); writer.print(" mParent="); writer.println(mParent); + } writer.print(prefix); writer.print(" mCurState="); writer.print(mCurState); writer.print(" mStateSaved="); writer.print(mStateSaved); writer.print(" mDestroyed="); writer.println(mDestroyed); @@ -809,7 +825,9 @@ final class FragmentManagerImpl extends FragmentManager { } } f.mActivity = mActivity; - f.mFragmentManager = mActivity.mFragments; + f.mParentFragment = mParent; + f.mFragmentManager = mParent != null + ? mParent.mChildFragmentManager : mActivity.mFragments; f.mCalled = false; f.onAttach(mActivity); if (!f.mCalled) { @@ -817,14 +835,9 @@ final class FragmentManagerImpl extends FragmentManager { + " 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.performCreate(f.mSavedFragmentState); } f.mRetaining = false; if (f.mFromLayout) { @@ -845,7 +858,7 @@ final class FragmentManagerImpl extends FragmentManager { if (!f.mFromLayout) { ViewGroup container = null; if (f.mContainerId != 0) { - container = (ViewGroup)mActivity.findViewById(f.mContainerId); + container = (ViewGroup)mContainer.findViewById(f.mContainerId); if (container == null && !f.mRestored) { throwException(new IllegalArgumentException( "No view found for id 0x" @@ -873,14 +886,9 @@ final class FragmentManagerImpl extends FragmentManager { } } - f.mCalled = false; - f.onActivityCreated(f.mSavedFragmentState); - if (!f.mCalled) { - throw new SuperNotCalledException("Fragment " + f - + " did not call through to super.onActivityCreated()"); - } + f.performActivityCreated(f.mSavedFragmentState); if (f.mView != null) { - f.restoreViewState(); + f.restoreViewState(f.mSavedFragmentState); } f.mSavedFragmentState = null; } @@ -888,23 +896,13 @@ final class FragmentManagerImpl extends FragmentManager { 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.performResume(); // Get rid of this in case we saved it and never needed it. f.mSavedFragmentState = null; f.mSavedViewState = null; @@ -915,23 +913,13 @@ final class FragmentManagerImpl extends FragmentManager { 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.performPause(); 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: case Fragment.ACTIVITY_CREATED: @@ -944,12 +932,7 @@ final class FragmentManagerImpl extends FragmentManager { 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) { Animator anim = null; if (mCurState > Fragment.INITIALIZING && !mDestroyed) { @@ -1008,12 +991,7 @@ final class FragmentManagerImpl extends FragmentManager { } 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.performDestroy(); } f.mCalled = false; @@ -1027,6 +1005,7 @@ final class FragmentManagerImpl extends FragmentManager { makeInactive(f); } else { f.mActivity = null; + f.mParentFragment = null; f.mFragmentManager = null; } } @@ -1050,11 +1029,11 @@ final class FragmentManagerImpl extends FragmentManager { if (mActivity == null && newState != Fragment.INITIALIZING) { throw new IllegalStateException("No activity"); } - + if (!always && mCurState == newState) { return; } - + mCurState = newState; if (mActive != null) { boolean loadersRunning = false; @@ -1099,11 +1078,11 @@ final class FragmentManagerImpl extends FragmentManager { if (mActive == null) { mActive = new ArrayList(); } - f.setIndex(mActive.size()); + f.setIndex(mActive.size(), mParent); mActive.add(f); } else { - f.setIndex(mAvailIndices.remove(mAvailIndices.size()-1)); + f.setIndex(mAvailIndices.remove(mAvailIndices.size()-1), mParent); mActive.set(f.mIndex, f); } if (DEBUG) Log.v(TAG, "Allocated fragment index " + f); @@ -1120,7 +1099,7 @@ final class FragmentManagerImpl extends FragmentManager { mAvailIndices = new ArrayList(); } mAvailIndices.add(f.mIndex); - mActivity.invalidateFragmentIndex(f.mIndex); + mActivity.invalidateFragment(f.mWho); f.initState(); } @@ -1296,7 +1275,7 @@ final class FragmentManagerImpl extends FragmentManager { 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)) { + if (f != null && (f=f.findFragmentByWho(who)) != null) { return f; } } @@ -1566,7 +1545,7 @@ final class FragmentManagerImpl extends FragmentManager { if (mStateBundle == null) { mStateBundle = new Bundle(); } - f.onSaveInstanceState(mStateBundle); + f.performSaveInstanceState(mStateBundle); if (!mStateBundle.isEmpty()) { result = mStateBundle; mStateBundle = null; @@ -1735,7 +1714,7 @@ final class FragmentManagerImpl extends FragmentManager { for (int i=0; i(); + if (f != null) { + if (f.performCreateOptionsMenu(menu, inflater)) { + show = true; + if (newMenus == null) { + newMenus = new ArrayList(); + } + newMenus.add(f); } - newMenus.add(f); } } } @@ -1916,9 +1904,10 @@ final class FragmentManagerImpl extends FragmentManager { if (mAdded != null) { for (int i=0; i mInactiveLoaders = new SparseArray(); + final String mWho; + Activity mActivity; boolean mStarted; boolean mRetaining; @@ -529,7 +530,8 @@ class LoaderManagerImpl extends LoaderManager { } } - LoaderManagerImpl(Activity activity, boolean started) { + LoaderManagerImpl(String who, Activity activity, boolean started) { + mWho = who; mActivity = activity; mStarted = started; }