diff options
| -rw-r--r-- | api/current.txt | 12 | ||||
| -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 |
6 files changed, 163 insertions, 23 deletions
diff --git a/api/current.txt b/api/current.txt index 64ce71f56429..8ef07debd226 100644 --- a/api/current.txt +++ b/api/current.txt @@ -2893,6 +2893,7 @@ package android.app { method public void registerForContextMenu(android.view.View); method public void setArguments(android.os.Bundle); method public void setHasOptionsMenu(boolean); + method public void setInitialSavedState(android.app.Fragment.SavedState); method public void setRetainInstance(boolean); method public void setTargetFragment(android.app.Fragment, int); method public void startActivity(android.content.Intent); @@ -2904,6 +2905,12 @@ package android.app { ctor public Fragment.InstantiationException(java.lang.String, java.lang.Exception); } + public static class Fragment.SavedState implements android.os.Parcelable { + method public int describeContents(); + method public void writeToParcel(android.os.Parcel, int); + field public static final android.os.Parcelable.ClassLoaderCreator CREATOR; + } + public class FragmentBreadCrumbs extends android.view.ViewGroup implements android.app.FragmentManager.OnBackStackChangedListener { ctor public FragmentBreadCrumbs(android.content.Context); ctor public FragmentBreadCrumbs(android.content.Context, android.util.AttributeSet); @@ -2941,6 +2948,7 @@ package android.app { method public abstract boolean popBackStackImmediate(int, int); method public abstract void putFragment(android.os.Bundle, java.lang.String, android.app.Fragment); method public abstract void removeOnBackStackChangedListener(android.app.FragmentManager.OnBackStackChangedListener); + method public abstract android.app.Fragment.SavedState saveFragmentInstanceState(android.app.Fragment); field public static final int POP_BACK_STACK_INCLUSIVE = 1; // 0x1 } @@ -14164,6 +14172,10 @@ package android.os { field public static final int PARCELABLE_WRITE_RETURN_VALUE = 1; // 0x1 } + public static abstract interface Parcelable.ClassLoaderCreator implements android.os.Parcelable.Creator { + method public abstract T createFromParcel(android.os.Parcel, java.lang.ClassLoader); + } + public static abstract interface Parcelable.Creator { method public abstract T createFromParcel(android.os.Parcel); method public abstract T[] newArray(int); diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java index c102a38c2a55..7e94cf29e092 100644 --- a/core/java/android/app/ActivityThread.java +++ b/core/java/android/app/ActivityThread.java @@ -1884,7 +1884,7 @@ public final class ActivityThread { } deliverNewIntents(r, intents); if (resumed) { - mInstrumentation.callActivityOnResume(r.activity); + r.activity.performResume(); r.activity.mTemporaryPause = false; } } @@ -2850,7 +2850,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 6f0bbd7d28a3..14ffd3be78ca 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 0da656fb6419..2164ada862b9 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 6b352158120c..e9ed67650ca4 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 0a4b60fdd811..594fbb2c46e5 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); + } } |