diff --git a/api/current.xml b/api/current.xml
index f8b069953e3e3..cabd07d39a0b0 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -30627,6 +30627,19 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
CREATOR
+ = new Parcelable.ClassLoaderCreator() {
+ 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.
@@ -623,6 +668,22 @@ public class Fragment implements ComponentCallbacks, OnCreateContextMenuListener
return mArguments;
}
+ /**
+ * 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
diff --git a/core/java/android/app/FragmentManager.java b/core/java/android/app/FragmentManager.java
index 0da656fb64196..2164ada862b98 100644
--- a/core/java/android/app/FragmentManager.java
+++ b/core/java/android/app/FragmentManager.java
@@ -273,6 +273,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:
+ *
+ *
+ * - The Fragment must currently be attached to the FragmentManager.
+ *
- A new Fragment created using this saved state must be the same class
+ * type as the Fragment it was created from.
+ *
- 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.
+ *
+ *
+ * @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.
*
@@ -491,6 +515,19 @@ final class FragmentManagerImpl extends FragmentManager {
return f;
}
+ @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);
@@ -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();
+ } 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 6b352158120c2..e9ed67650ca46 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)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 0a4b60fdd811a..594fbb2c46e55 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 extends Creator {
+ /**
+ * 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);
+ }
}