diff options
| author | Dianne Hackborn <hackbod@google.com> | 2011-06-02 19:30:34 -0700 |
|---|---|---|
| committer | Android Git Automerger <android-git-automerger@android.com> | 2011-06-02 19:30:34 -0700 |
| commit | 758b67b12386a6ea52d520aef455c3150c9bae03 (patch) | |
| tree | 8800e537876a76e17b8366d68abbe40d0a69b1a8 /core/java/android | |
| parent | 2e543dc188c3c2e8f8a785e403c95b7e22fa6262 (diff) | |
| parent | b46ed7636be9341b6ce0b158b3d86f34a437e6da (diff) | |
| download | frameworks_base-758b67b12386a6ea52d520aef455c3150c9bae03.zip frameworks_base-758b67b12386a6ea52d520aef455c3150c9bae03.tar.gz frameworks_base-758b67b12386a6ea52d520aef455c3150c9bae03.tar.bz2 | |
am b46ed763: Add new Fragment API for explicitly saving/restoring state.
* commit 'b46ed7636be9341b6ce0b158b3d86f34a437e6da':
Add new Fragment API for explicitly saving/restoring state.
Diffstat (limited to 'core/java/android')
| -rw-r--r-- | core/java/android/app/ActivityThread.java | 4 | ||||
| -rw-r--r-- | core/java/android/app/Fragment.java | 61 | ||||
| -rw-r--r-- | core/java/android/app/FragmentManager.java | 88 | ||||
| -rw-r--r-- | core/java/android/os/Parcel.java | 3 | ||||
| -rw-r--r-- | core/java/android/os/Parcelable.java | 18 |
5 files changed, 151 insertions, 23 deletions
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java index 69cb27e..a61147a 100644 --- a/core/java/android/app/ActivityThread.java +++ b/core/java/android/app/ActivityThread.java @@ -1875,7 +1875,7 @@ public final class ActivityThread { } deliverNewIntents(r, intents); if (resumed) { - mInstrumentation.callActivityOnResume(r.activity); + r.activity.performResume(); r.activity.mTemporaryPause = false; } } @@ -2831,7 +2831,7 @@ public final class ActivityThread { } deliverResults(r, res.results); if (resumed) { - mInstrumentation.callActivityOnResume(r.activity); + r.activity.performResume(); r.activity.mTemporaryPause = false; } } diff --git a/core/java/android/app/Fragment.java b/core/java/android/app/Fragment.java index 6f0bbd7..14ffd3b 100644 --- a/core/java/android/app/Fragment.java +++ b/core/java/android/app/Fragment.java @@ -450,6 +450,51 @@ public class Fragment implements ComponentCallbacks, OnCreateContextMenuListener boolean mCheckedForLoaderManager; /** + * State information that has been retrieved from a fragment instance + * through {@link FragmentManager#saveFragmentInstanceState(Fragment) + * FragmentManager.saveFragmentInstanceState}. + */ + public static class SavedState implements Parcelable { + final Bundle mState; + + SavedState(Bundle state) { + mState = state; + } + + SavedState(Parcel in, ClassLoader loader) { + mState = in.readBundle(); + if (loader != null && mState != null) { + mState.setClassLoader(loader); + } + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeBundle(mState); + } + + public static final Parcelable.ClassLoaderCreator<SavedState> CREATOR + = new Parcelable.ClassLoaderCreator<SavedState>() { + public SavedState createFromParcel(Parcel in) { + return new SavedState(in, null); + } + + public SavedState createFromParcel(Parcel in, ClassLoader loader) { + return new SavedState(in, loader); + } + + public SavedState[] newArray(int size) { + return new SavedState[size]; + } + }; + } + + /** * Thrown by {@link Fragment#instantiate(Context, String, Bundle)} when * there is an instantiation failure. */ @@ -624,6 +669,22 @@ public class Fragment implements ComponentCallbacks, OnCreateContextMenuListener } /** + * Set the initial saved state that this Fragment should restore itself + * from when first being constructed, as returned by + * {@link FragmentManager#saveFragmentInstanceState(Fragment) + * FragmentManager.saveFragmentInstanceState}. + * + * @param state The state the fragment should be restored from. + */ + public void setInitialSavedState(SavedState state) { + if (mIndex >= 0) { + throw new IllegalStateException("Fragment already active"); + } + mSavedFragmentState = state != null && state.mState != null + ? state.mState : null; + } + + /** * Optional target for this fragment. This may be used, for example, * if this fragment is being started by another, and when done wants to * give a result back to the first. The target set here is retained diff --git a/core/java/android/app/FragmentManager.java b/core/java/android/app/FragmentManager.java index 0da656f..2164ada 100644 --- a/core/java/android/app/FragmentManager.java +++ b/core/java/android/app/FragmentManager.java @@ -274,6 +274,30 @@ public abstract class FragmentManager { public abstract Fragment getFragment(Bundle bundle, String key); /** + * Save the current instance state of the given Fragment. This can be + * used later when creating a new instance of the Fragment and adding + * it to the fragment manager, to have it create itself to match the + * current state returned here. Note that there are limits on how + * this can be used: + * + * <ul> + * <li>The Fragment must currently be attached to the FragmentManager. + * <li>A new Fragment created using this saved state must be the same class + * type as the Fragment it was created from. + * <li>The saved state can not contain dependencies on other fragments -- + * that is it can't use {@link #putFragment(Bundle, String, Fragment)} to + * store a fragment reference because that reference may not be valid when + * this saved state is later used. Likewise the Fragment's target and + * result code are not included in this state. + * </ul> + * + * @param f The Fragment whose state is to be saved. + * @return The generated state. This will be null if there was no + * interesting state created by the fragment. + */ + public abstract Fragment.SavedState saveFragmentInstanceState(Fragment f); + + /** * Print the FragmentManager's state into the given stream. * * @param prefix Text to print at the front of each line. @@ -492,6 +516,19 @@ final class FragmentManagerImpl extends FragmentManager { } @Override + public Fragment.SavedState saveFragmentInstanceState(Fragment fragment) { + if (fragment.mIndex < 0) { + throw new IllegalStateException("Fragment " + fragment + + " is not currently in the FragmentManager"); + } + if (fragment.mState > Fragment.INITIALIZING) { + Bundle result = saveFragmentBasicState(fragment); + return result != null ? new Fragment.SavedState(result) : null; + } + return null; + } + + @Override public String toString() { StringBuilder sb = new StringBuilder(128); sb.append("FragmentManager{"); @@ -715,7 +752,6 @@ final class FragmentManagerImpl extends FragmentManager { if (f.mView != null) { f.mView.setSaveFromParentEnabled(false); if (f.mHidden) f.mView.setVisibility(View.GONE); - f.restoreViewState(); f.onViewCreated(f.mView, f.mSavedFragmentState); } } @@ -747,7 +783,6 @@ final class FragmentManagerImpl extends FragmentManager { container.addView(f.mView); } if (f.mHidden) f.mView.setVisibility(View.GONE); - f.restoreViewState(); f.onViewCreated(f.mView, f.mSavedFragmentState); } } @@ -759,6 +794,7 @@ final class FragmentManagerImpl extends FragmentManager { + " did not call through to super.onActivityCreated()"); } if (f.mView != null) { + f.restoreViewState(); } f.mSavedFragmentState = null; } @@ -1375,6 +1411,8 @@ final class FragmentManagerImpl extends FragmentManager { } if (mStateArray == null) { mStateArray = new SparseArray<Parcelable>(); + } else { + mStateArray.clear(); } f.mView.saveHierarchyState(mStateArray); if (mStateArray.size() > 0) { @@ -1383,6 +1421,32 @@ final class FragmentManagerImpl extends FragmentManager { } } + Bundle saveFragmentBasicState(Fragment f) { + Bundle result = null; + + if (mStateBundle == null) { + mStateBundle = new Bundle(); + } + f.onSaveInstanceState(mStateBundle); + if (!mStateBundle.isEmpty()) { + result = mStateBundle; + mStateBundle = null; + } + + if (f.mView != null) { + saveFragmentViewState(f); + if (f.mSavedViewState != null) { + if (result == null) { + result = new Bundle(); + } + result.putSparseParcelableArray( + FragmentManagerImpl.VIEW_STATE_TAG, f.mSavedViewState); + } + } + + return result; + } + Parcelable saveAllState() { // Make sure all pending operations have now been executed to get // our state update-to-date. @@ -1407,25 +1471,7 @@ final class FragmentManagerImpl extends FragmentManager { active[i] = fs; if (f.mState > 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); - } - } + fs.mSavedFragmentState = saveFragmentBasicState(f); if (f.mTarget != null) { if (f.mTarget.mIndex < 0) { diff --git a/core/java/android/os/Parcel.java b/core/java/android/os/Parcel.java index 6b35215..e9ed676 100644 --- a/core/java/android/os/Parcel.java +++ b/core/java/android/os/Parcel.java @@ -1980,6 +1980,9 @@ public final class Parcel { } } + if (creator instanceof Parcelable.ClassLoaderCreator<?>) { + return ((Parcelable.ClassLoaderCreator<T>)creator).createFromParcel(this, loader); + } return creator.createFromParcel(this); } diff --git a/core/java/android/os/Parcelable.java b/core/java/android/os/Parcelable.java index 0a4b60f..594fbb2 100644 --- a/core/java/android/os/Parcelable.java +++ b/core/java/android/os/Parcelable.java @@ -113,4 +113,22 @@ public interface Parcelable { */ public T[] newArray(int size); } + + /** + * Specialization of {@link Creator} that allows you to receive the + * ClassLoader the object is being created in. + */ + public interface ClassLoaderCreator<T> extends Creator<T> { + /** + * Create a new instance of the Parcelable class, instantiating it + * from the given Parcel whose data had previously been written by + * {@link Parcelable#writeToParcel Parcelable.writeToParcel()} and + * using the given ClassLoader. + * + * @param source The Parcel to read the object's data from. + * @param loader The ClassLoader that this object is being created in. + * @return Returns a new instance of the Parcelable class. + */ + public T createFromParcel(Parcel source, ClassLoader loader); + } } |
