diff --git a/api/current.xml b/api/current.xml index 4e7ebf6bb58d6..855f843227ef4 100644 --- a/api/current.xml +++ b/api/current.xml @@ -30529,6 +30529,21 @@ visibility="public" > + + + + + + + + + + + + + + 0; + } + /** * Subclasses can not override equals(). */ @@ -946,6 +959,19 @@ public class Fragment implements ComponentCallbacks, OnCreateContextMenuListener mCalled = true; } + /** + * Called immediately after {@link #onCreateView(LayoutInflater, ViewGroup, Bundle)} + * has returned, but before any saved state has been restored in to the view. + * This gives subclasses a chance to initialize themselves once + * they know their view hierarchy has been completely created. The fragment's + * view hierarchy is not however attached to its parent at this point. + * @param view The View returned by {@link #onCreateView(LayoutInflater, ViewGroup, Bundle)}. + * @param savedInstanceState If non-null, this fragment is being re-constructed + * from a previous saved state as given here. + */ + public void onViewCreated(View view, Bundle savedInstanceState) { + } + /** * Called to have the fragment instantiate its user interface view. * This is optional, and non-graphical fragments can return null (which @@ -1280,6 +1306,7 @@ public class Fragment implements ComponentCallbacks, OnCreateContextMenuListener writer.print(" mFromLayout="); writer.print(mFromLayout); writer.print(" mInLayout="); writer.println(mInLayout); writer.print(prefix); writer.print("mHidden="); writer.print(mHidden); + writer.print(" mDetached="); writer.print(mDetached); writer.print(" mRetainInstance="); writer.print(mRetainInstance); writer.print(" mRetaining="); writer.print(mRetaining); writer.print(" mHasMenu="); writer.println(mHasMenu); diff --git a/core/java/android/app/FragmentManager.java b/core/java/android/app/FragmentManager.java index ab60cf016ba9c..0da656fb64196 100644 --- a/core/java/android/app/FragmentManager.java +++ b/core/java/android/app/FragmentManager.java @@ -714,13 +714,14 @@ final class FragmentManagerImpl extends FragmentManager { null, f.mSavedFragmentState); if (f.mView != null) { f.mView.setSaveFromParentEnabled(false); + if (f.mHidden) f.mView.setVisibility(View.GONE); f.restoreViewState(); - if (f.mHidden) f.mView.setVisibility(View.GONE); + f.onViewCreated(f.mView, f.mSavedFragmentState); } } case Fragment.CREATED: if (newState > Fragment.CREATED) { - if (DEBUG) Log.v(TAG, "moveto CONTENT: " + f); + if (DEBUG) Log.v(TAG, "moveto ACTIVITY_CREATED: " + f); if (!f.mFromLayout) { ViewGroup container = null; if (f.mContainerId != 0) { @@ -744,9 +745,10 @@ final class FragmentManagerImpl extends FragmentManager { anim.start(); } container.addView(f.mView); - f.restoreViewState(); } - if (f.mHidden) f.mView.setVisibility(View.GONE); + if (f.mHidden) f.mView.setVisibility(View.GONE); + f.restoreViewState(); + f.onViewCreated(f.mView, f.mSavedFragmentState); } } @@ -756,10 +758,13 @@ final class FragmentManagerImpl extends FragmentManager { throw new SuperNotCalledException("Fragment " + f + " did not call through to super.onActivityCreated()"); } + if (f.mView != null) { + } f.mSavedFragmentState = null; } case Fragment.ACTIVITY_CREATED: - if (newState > Fragment.ACTIVITY_CREATED) { + case Fragment.STOPPED: + if (newState > Fragment.STOPPED) { if (DEBUG) Log.v(TAG, "moveto STARTED: " + f); f.mCalled = false; f.onStart(); @@ -803,9 +808,10 @@ final class FragmentManagerImpl extends FragmentManager { + " did not call through to super.onStop()"); } } + case Fragment.STOPPED: case Fragment.ACTIVITY_CREATED: if (newState < Fragment.ACTIVITY_CREATED) { - if (DEBUG) Log.v(TAG, "movefrom CONTENT: " + f); + if (DEBUG) Log.v(TAG, "movefrom ACTIVITY_CREATED: " + f); if (f.mView != null) { // Need to save the current view state if not // done already. @@ -971,32 +977,36 @@ final class FragmentManagerImpl extends FragmentManager { 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); + makeActive(fragment); + if (!fragment.mDetached) { + mAdded.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); + final boolean inactive = !fragment.isInBackStack(); + if (!fragment.mDetached || inactive) { + mAdded.remove(fragment); + if (fragment.mHasMenu) { + mNeedMenuInvalidate = true; + } + fragment.mAdded = false; + fragment.mRemoving = true; + moveToState(fragment, inactive ? Fragment.INITIALIZING : Fragment.CREATED, + transition, transitionStyle); + if (inactive) { + makeInactive(fragment); + } } } @@ -1052,6 +1062,39 @@ final class FragmentManagerImpl extends FragmentManager { } } + public void detachFragment(Fragment fragment, int transition, int transitionStyle) { + if (DEBUG) Log.v(TAG, "detach: " + fragment); + if (!fragment.mDetached) { + fragment.mDetached = true; + if (fragment.mAdded) { + // We are not already in back stack, so need to remove the fragment. + mAdded.remove(fragment); + if (fragment.mHasMenu) { + mNeedMenuInvalidate = true; + } + fragment.mAdded = false; + fragment.mRemoving = true; + moveToState(fragment, Fragment.CREATED, transition, transitionStyle); + } + } + } + + public void attachFragment(Fragment fragment, int transition, int transitionStyle) { + if (DEBUG) Log.v(TAG, "attach: " + fragment); + if (fragment.mDetached) { + fragment.mDetached = false; + if (!fragment.mAdded) { + mAdded.add(fragment); + fragment.mAdded = true; + fragment.mRemoving = false; + if (fragment.mHasMenu) { + mNeedMenuInvalidate = true; + } + moveToState(fragment, mCurState, transition, transitionStyle); + } + } + } + public Fragment findFragmentById(int id) { if (mActive != null) { // First look through added fragments. @@ -1594,7 +1637,7 @@ final class FragmentManagerImpl extends FragmentManager { } public void dispatchStop() { - moveToState(Fragment.ACTIVITY_CREATED, false); + moveToState(Fragment.STOPPED, false); } public void dispatchDestroy() { diff --git a/core/java/android/app/FragmentTransaction.java b/core/java/android/app/FragmentTransaction.java index 0cc774d3d2f9e..15b873b20c668 100644 --- a/core/java/android/app/FragmentTransaction.java +++ b/core/java/android/app/FragmentTransaction.java @@ -86,6 +86,31 @@ public abstract class FragmentTransaction { */ public abstract FragmentTransaction show(Fragment fragment); + /** + * Detach the given fragment from the UI. This is the same state as + * when it is put on the back stack: the fragment is removed from + * the UI, however its state is still being actively managed by the + * fragment manager. When going into this state its view hierarchy + * is destroyed. + * + * @param fragment The fragment to be detached. + * + * @return Returns the same FragmentTransaction instance. + */ + public abstract FragmentTransaction detach(Fragment fragment); + + /** + * Re-attach a fragment after it had previously been deatched from + * the UI with {@link #detach(Fragment)}. This + * causes its view hierarchy to be re-created, attached to the UI, + * and displayed. + * + * @param fragment The fragment to be attached. + * + * @return Returns the same FragmentTransaction instance. + */ + public abstract FragmentTransaction attach(Fragment fragment); + /** * @return true if this transaction contains no operations, * false otherwise. diff --git a/core/java/android/app/ListFragment.java b/core/java/android/app/ListFragment.java index 6e2f4b6b54d32..a5ee26c9a22f0 100644 --- a/core/java/android/app/ListFragment.java +++ b/core/java/android/app/ListFragment.java @@ -195,11 +195,11 @@ public class ListFragment extends Fragment { } /** - * Attach to list view once Fragment is ready to run. + * Attach to list view once the view hierarchy has been created. */ @Override - public void onActivityCreated(Bundle savedInstanceState) { - super.onActivityCreated(savedInstanceState); + public void onViewCreated(View view, Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); ensureList(); }