diff options
author | Dianne Hackborn <hackbod@google.com> | 2012-09-04 18:48:15 -0700 |
---|---|---|
committer | Dianne Hackborn <hackbod@google.com> | 2012-09-06 11:05:53 -0700 |
commit | 62bea2f1710be0d1a42c07109fd4307ded660d3b (patch) | |
tree | f772341cd06cd3df43bea1572361d226f4faed2f /core/java/android/app | |
parent | 18e876806718e28edaa3cd9bb0262a9b400bc82b (diff) | |
download | frameworks_base-62bea2f1710be0d1a42c07109fd4307ded660d3b.zip frameworks_base-62bea2f1710be0d1a42c07109fd4307ded660d3b.tar.gz frameworks_base-62bea2f1710be0d1a42c07109fd4307ded660d3b.tar.bz2 |
Nested fragments.
Change-Id: I79acc19b391352c16b06afee2ca543223c38e364
Diffstat (limited to 'core/java/android/app')
-rw-r--r-- | core/java/android/app/Activity.java | 70 | ||||
-rw-r--r-- | core/java/android/app/Fragment.java | 318 | ||||
-rw-r--r-- | core/java/android/app/FragmentManager.java | 147 | ||||
-rw-r--r-- | core/java/android/app/LoaderManager.java | 6 |
4 files changed, 423 insertions, 118 deletions
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java index 99dfccb..05b04dc 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<String, Object> children; ArrayList<Fragment> fragments; - SparseArray<LoaderManagerImpl> loaders; + HashMap<String, LoaderManagerImpl> 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<LoaderManagerImpl> mAllLoaderManagers; + HashMap<String, LoaderManagerImpl> 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<LoaderManagerImpl>(); + mAllLoaderManagers = new HashMap<String, LoaderManagerImpl>(); } - 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<loaders.length; i++) { + LoaderManagerImpl lm = loaders[i]; + if (lm.mRetaining) { + retainLoaders = true; + } else { + lm.doDestroy(); + mAllLoaderManagers.remove(lm.mWho); + } } } } @@ -1643,13 +1655,13 @@ public class Activity extends ContextThemeWrapper return mFragments; } - void invalidateFragmentIndex(int index) { + void invalidateFragment(String who) { //Log.v(TAG, "invalidateFragmentIndex: index=" + index); if (mAllLoaderManagers != null) { - LoaderManagerImpl lm = mAllLoaderManagers.get(index); + LoaderManagerImpl lm = mAllLoaderManagers.get(who); if (lm != null && !lm.mRetaining) { lm.doDestroy(); - mAllLoaderManagers.remove(index); + mAllLoaderManagers.remove(who); } } } @@ -4739,6 +4751,10 @@ public class Activity extends ContextThemeWrapper * @param args additional arguments to the dump request. */ public void dump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) { + dumpInner(prefix, fd, writer, args); + } + + void dumpInner(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) { writer.print(prefix); writer.print("Local Activity "); writer.print(Integer.toHexString(System.identityHashCode(this))); writer.println(" State:"); @@ -5019,7 +5035,7 @@ public class Activity extends ContextThemeWrapper Configuration config) { attachBaseContext(context); - mFragments.attachActivity(this); + mFragments.attachActivity(this, mContainer, null); mWindow = PolicyManager.makeNewWindow(this); mWindow.setCallback(this); @@ -5080,10 +5096,14 @@ public class Activity extends ContextThemeWrapper } mFragments.dispatchStart(); if (mAllLoaderManagers != null) { - for (int i=mAllLoaderManagers.size()-1; 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<loaders.length; i++) { + LoaderManagerImpl lm = loaders[i]; + lm.finishRetain(); + lm.doReportStart(); + } } } } diff --git a/core/java/android/app/Fragment.java b/core/java/android/app/Fragment.java index 28876d3..3ff9df5 100644 --- a/core/java/android/app/Fragment.java +++ b/core/java/android/app/Fragment.java @@ -85,7 +85,7 @@ final class FragmentState implements Parcelable { mSavedFragmentState = in.readBundle(); } - public Fragment instantiate(Activity activity) { + public Fragment instantiate(Activity activity, Fragment parent) { if (mInstance != null) { return mInstance; } @@ -100,7 +100,7 @@ final class FragmentState implements Parcelable { mSavedFragmentState.setClassLoader(activity.getClassLoader()); mInstance.mSavedFragmentState = mSavedFragmentState; } - mInstance.setIndex(mIndex); + mInstance.setIndex(mIndex, parent); mInstance.mFromLayout = mFromLayout; mInstance.mRestored = true; mInstance.mFragmentId = mFragmentId; @@ -207,6 +207,8 @@ final class FragmentState implements Parcelable { * with the fragment. * <li> {@link #onActivityCreated} tells the fragment that its activity has * completed its own {@link Activity#onCreate Activity.onCreate()}. + * <li> {@link #onViewStateRestored} tells the fragment that all of the saved + * state of its view hierarchy has been restored. * <li> {@link #onStart} makes the fragment visible to the user (based on its * containing activity being started). * <li> {@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,12 +803,35 @@ 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. + * + * <p>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. */ final public boolean isAdded() { @@ -880,6 +921,10 @@ public class Fragment implements ComponentCallbacks2, OnCreateContextMenuListene * </ul> */ 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 52a6557..eaaf0d7 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; @@ -381,6 +379,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. */ final class FragmentManagerImpl extends FragmentManager { @@ -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<Fragment>(); } - 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<Integer>(); } 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<fms.mActive.length; i++) { FragmentState fs = fms.mActive[i]; if (fs != null) { - Fragment f = fs.instantiate(mActivity); + Fragment f = fs.instantiate(mActivity, mParent); if (DEBUG) Log.v(TAG, "restoreAllState: adding #" + i + ": " + f); mActive.add(f); // Now that the fragment is instantiated (or came from being @@ -1803,9 +1782,11 @@ final class FragmentManagerImpl extends FragmentManager { } } - public void attachActivity(Activity activity) { + public void attachActivity(Activity activity, FragmentContainer container, Fragment parent) { if (mActivity != null) throw new IllegalStateException("Already attached"); mActivity = activity; + mContainer = container; + mParent = parent; } public void noteStateNotSaved() { @@ -1840,11 +1821,17 @@ final class FragmentManagerImpl extends FragmentManager { moveToState(Fragment.STOPPED, false); } + public void dispatchDestroyView() { + moveToState(Fragment.CREATED, false); + } + public void dispatchDestroy() { mDestroyed = true; execPendingActions(); moveToState(Fragment.INITIALIZING, false); mActivity = null; + mContainer = null; + mParent = null; } public void dispatchConfigurationChanged(Configuration newConfig) { @@ -1852,7 +1839,7 @@ final class FragmentManagerImpl extends FragmentManager { for (int i=0; i<mAdded.size(); i++) { Fragment f = mAdded.get(i); if (f != null) { - f.onConfigurationChanged(newConfig); + f.performConfigurationChanged(newConfig); } } } @@ -1863,7 +1850,7 @@ final class FragmentManagerImpl extends FragmentManager { for (int i=0; i<mAdded.size(); i++) { Fragment f = mAdded.get(i); if (f != null) { - f.onLowMemory(); + f.performLowMemory(); } } } @@ -1874,7 +1861,7 @@ final class FragmentManagerImpl extends FragmentManager { for (int i=0; i<mAdded.size(); i++) { Fragment f = mAdded.get(i); if (f != null) { - f.onTrimMemory(level); + f.performTrimMemory(level); } } } @@ -1886,13 +1873,14 @@ final class FragmentManagerImpl extends FragmentManager { if (mAdded != 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>(); + if (f != null) { + if (f.performCreateOptionsMenu(menu, inflater)) { + show = true; + if (newMenus == null) { + newMenus = new ArrayList<Fragment>(); + } + newMenus.add(f); } - newMenus.add(f); } } } @@ -1916,9 +1904,10 @@ final class FragmentManagerImpl extends FragmentManager { if (mAdded != 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); + if (f != null) { + if (f.performPrepareOptionsMenu(menu)) { + show = true; + } } } } @@ -1929,8 +1918,8 @@ final class FragmentManagerImpl extends FragmentManager { if (mAdded != 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)) { + if (f != null) { + if (f.performOptionsItemSelected(item)) { return true; } } @@ -1943,8 +1932,8 @@ final class FragmentManagerImpl extends FragmentManager { if (mAdded != null) { for (int i=0; i<mAdded.size(); i++) { Fragment f = mAdded.get(i); - if (f != null && !f.mHidden) { - if (f.onContextItemSelected(item)) { + if (f != null) { + if (f.performContextItemSelected(item)) { return true; } } @@ -1957,8 +1946,8 @@ final class FragmentManagerImpl extends FragmentManager { if (mAdded != 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); + if (f != null) { + f.performOptionsMenuClosed(menu); } } } diff --git a/core/java/android/app/LoaderManager.java b/core/java/android/app/LoaderManager.java index ff71ee7..fd0f0bf 100644 --- a/core/java/android/app/LoaderManager.java +++ b/core/java/android/app/LoaderManager.java @@ -17,7 +17,6 @@ package android.app; import android.content.Loader; -import android.content.Loader.OnLoadCanceledListener; import android.os.Bundle; import android.util.DebugUtils; import android.util.Log; @@ -213,6 +212,8 @@ class LoaderManagerImpl extends LoaderManager { // previously run loader until the new loader's data is available. final SparseArray<LoaderInfo> mInactiveLoaders = new SparseArray<LoaderInfo>(); + 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; } |