am b46ed763: Add new Fragment API for explicitly saving/restoring state.

* commit 'b46ed7636be9341b6ce0b158b3d86f34a437e6da':
  Add new Fragment API for explicitly saving/restoring state.
This commit is contained in:
Dianne Hackborn
2011-06-02 19:30:34 -07:00
committed by Android Git Automerger
6 changed files with 249 additions and 23 deletions

View File

@ -30627,6 +30627,19 @@
<parameter name="hasMenu" type="boolean">
</parameter>
</method>
<method name="setInitialSavedState"
return="void"
abstract="false"
native="false"
synchronized="false"
static="false"
final="false"
deprecated="not deprecated"
visibility="public"
>
<parameter name="state" type="android.app.Fragment.SavedState">
</parameter>
</method>
<method name="setRetainInstance"
return="void"
abstract="false"
@ -30718,6 +30731,53 @@
</parameter>
</constructor>
</class>
<class name="Fragment.SavedState"
extends="java.lang.Object"
abstract="false"
static="true"
final="false"
deprecated="not deprecated"
visibility="public"
>
<implements name="android.os.Parcelable">
</implements>
<method name="describeContents"
return="int"
abstract="false"
native="false"
synchronized="false"
static="false"
final="false"
deprecated="not deprecated"
visibility="public"
>
</method>
<method name="writeToParcel"
return="void"
abstract="false"
native="false"
synchronized="false"
static="false"
final="false"
deprecated="not deprecated"
visibility="public"
>
<parameter name="dest" type="android.os.Parcel">
</parameter>
<parameter name="flags" type="int">
</parameter>
</method>
<field name="CREATOR"
type="android.os.Parcelable.ClassLoaderCreator"
transient="false"
volatile="false"
static="true"
final="true"
deprecated="not deprecated"
visibility="public"
>
</field>
</class>
<class name="FragmentBreadCrumbs"
extends="android.view.ViewGroup"
abstract="false"
@ -31151,6 +31211,19 @@
<parameter name="listener" type="android.app.FragmentManager.OnBackStackChangedListener">
</parameter>
</method>
<method name="saveFragmentInstanceState"
return="android.app.Fragment.SavedState"
abstract="true"
native="false"
synchronized="false"
static="false"
final="false"
deprecated="not deprecated"
visibility="public"
>
<parameter name="f" type="android.app.Fragment">
</parameter>
</method>
<field name="POP_BACK_STACK_INCLUSIVE"
type="int"
transient="false"
@ -150858,6 +150931,31 @@
>
</field>
</interface>
<interface name="Parcelable.ClassLoaderCreator"
abstract="true"
static="true"
final="false"
deprecated="not deprecated"
visibility="public"
>
<implements name="android.os.Parcelable.Creator">
</implements>
<method name="createFromParcel"
return="T"
abstract="true"
native="false"
synchronized="false"
static="false"
final="false"
deprecated="not deprecated"
visibility="public"
>
<parameter name="source" type="android.os.Parcel">
</parameter>
<parameter name="loader" type="java.lang.ClassLoader">
</parameter>
</method>
</interface>
<interface name="Parcelable.Creator"
abstract="true"
static="true"

View File

@ -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;
}
}

View File

@ -449,6 +449,51 @@ public class Fragment implements ComponentCallbacks, OnCreateContextMenuListener
boolean mLoadersStarted;
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.
@ -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

View File

@ -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:
*
* <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.
*
@ -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<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) {

View File

@ -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);
}

View File

@ -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);
}
}