summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--api/current.txt12
-rw-r--r--core/java/android/app/ActivityThread.java4
-rw-r--r--core/java/android/app/Fragment.java61
-rw-r--r--core/java/android/app/FragmentManager.java88
-rw-r--r--core/java/android/os/Parcel.java3
-rw-r--r--core/java/android/os/Parcelable.java18
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);
+ }
}