Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b46ed763 authored by Dianne Hackborn's avatar Dianne Hackborn
Browse files

Add new Fragment API for explicitly saving/restoring state.

Also fix issue #4519821:
Blank screen displayed on tapping "Battery Use" option in the settings

We weren't correctly doing the full Activity resume code when coming
back from delivering a new Intent or result.

And fix a fragment problem where we still weren't correctly restoring
the state of list views.  (I think this was from a bad manual-merge
from master.)

Change-Id: If79dc7e998155c39ab8c04781f6c73a82238a9ef
parent e1718de6
Loading
Loading
Loading
Loading
+98 −0
Original line number Original line Diff line number Diff line
@@ -30627,6 +30627,19 @@
<parameter name="hasMenu" type="boolean">
<parameter name="hasMenu" type="boolean">
</parameter>
</parameter>
</method>
</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"
<method name="setRetainInstance"
 return="void"
 return="void"
 abstract="false"
 abstract="false"
@@ -30718,6 +30731,53 @@
</parameter>
</parameter>
</constructor>
</constructor>
</class>
</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"
<class name="FragmentBreadCrumbs"
 extends="android.view.ViewGroup"
 extends="android.view.ViewGroup"
 abstract="false"
 abstract="false"
@@ -31151,6 +31211,19 @@
<parameter name="listener" type="android.app.FragmentManager.OnBackStackChangedListener">
<parameter name="listener" type="android.app.FragmentManager.OnBackStackChangedListener">
</parameter>
</parameter>
</method>
</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"
<field name="POP_BACK_STACK_INCLUSIVE"
 type="int"
 type="int"
 transient="false"
 transient="false"
@@ -150858,6 +150931,31 @@
>
>
</field>
</field>
</interface>
</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"
<interface name="Parcelable.Creator"
 abstract="true"
 abstract="true"
 static="true"
 static="true"
+2 −2
Original line number Original line Diff line number Diff line
@@ -1875,7 +1875,7 @@ public final class ActivityThread {
            }
            }
            deliverNewIntents(r, intents);
            deliverNewIntents(r, intents);
            if (resumed) {
            if (resumed) {
                mInstrumentation.callActivityOnResume(r.activity);
                r.activity.performResume();
                r.activity.mTemporaryPause = false;
                r.activity.mTemporaryPause = false;
            }
            }
        }
        }
@@ -2831,7 +2831,7 @@ public final class ActivityThread {
            }
            }
            deliverResults(r, res.results);
            deliverResults(r, res.results);
            if (resumed) {
            if (resumed) {
                mInstrumentation.callActivityOnResume(r.activity);
                r.activity.performResume();
                r.activity.mTemporaryPause = false;
                r.activity.mTemporaryPause = false;
            }
            }
        }
        }
+61 −0
Original line number Original line Diff line number Diff line
@@ -449,6 +449,51 @@ public class Fragment implements ComponentCallbacks, OnCreateContextMenuListener
    boolean mLoadersStarted;
    boolean mLoadersStarted;
    boolean mCheckedForLoaderManager;
    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
     * Thrown by {@link Fragment#instantiate(Context, String, Bundle)} when
     * there is an instantiation failure.
     * there is an instantiation failure.
@@ -623,6 +668,22 @@ public class Fragment implements ComponentCallbacks, OnCreateContextMenuListener
        return mArguments;
        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,
     * Optional target for this fragment.  This may be used, for example,
     * if this fragment is being started by another, and when done wants to
     * if this fragment is being started by another, and when done wants to
+67 −21
Original line number Original line Diff line number Diff line
@@ -273,6 +273,30 @@ public abstract class FragmentManager {
     */
     */
    public abstract Fragment getFragment(Bundle bundle, String key);
    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.
     * Print the FragmentManager's state into the given stream.
     *
     *
@@ -491,6 +515,19 @@ final class FragmentManagerImpl extends FragmentManager {
        return f;
        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
    @Override
    public String toString() {
    public String toString() {
        StringBuilder sb = new StringBuilder(128);
        StringBuilder sb = new StringBuilder(128);
@@ -715,7 +752,6 @@ final class FragmentManagerImpl extends FragmentManager {
                        if (f.mView != null) {
                        if (f.mView != null) {
                            f.mView.setSaveFromParentEnabled(false);
                            f.mView.setSaveFromParentEnabled(false);
                            if (f.mHidden) f.mView.setVisibility(View.GONE);
                            if (f.mHidden) f.mView.setVisibility(View.GONE);
                            f.restoreViewState();
                            f.onViewCreated(f.mView, f.mSavedFragmentState);
                            f.onViewCreated(f.mView, f.mSavedFragmentState);
                        }
                        }
                    }
                    }
@@ -747,7 +783,6 @@ final class FragmentManagerImpl extends FragmentManager {
                                    container.addView(f.mView);
                                    container.addView(f.mView);
                                }
                                }
                                if (f.mHidden) f.mView.setVisibility(View.GONE);
                                if (f.mHidden) f.mView.setVisibility(View.GONE);
                                f.restoreViewState();
                                f.onViewCreated(f.mView, f.mSavedFragmentState);
                                f.onViewCreated(f.mView, f.mSavedFragmentState);
                            }
                            }
                        }
                        }
@@ -759,6 +794,7 @@ final class FragmentManagerImpl extends FragmentManager {
                                    + " did not call through to super.onActivityCreated()");
                                    + " did not call through to super.onActivityCreated()");
                        }
                        }
                        if (f.mView != null) {
                        if (f.mView != null) {
                            f.restoreViewState();
                        }
                        }
                        f.mSavedFragmentState = null;
                        f.mSavedFragmentState = null;
                    }
                    }
@@ -1375,6 +1411,8 @@ final class FragmentManagerImpl extends FragmentManager {
        }
        }
        if (mStateArray == null) {
        if (mStateArray == null) {
            mStateArray = new SparseArray<Parcelable>();
            mStateArray = new SparseArray<Parcelable>();
        } else {
            mStateArray.clear();
        }
        }
        f.mView.saveHierarchyState(mStateArray);
        f.mView.saveHierarchyState(mStateArray);
        if (mStateArray.size() > 0) {
        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() {
    Parcelable saveAllState() {
        // Make sure all pending operations have now been executed to get
        // Make sure all pending operations have now been executed to get
        // our state update-to-date.
        // our state update-to-date.
@@ -1407,25 +1471,7 @@ final class FragmentManagerImpl extends FragmentManager {
                active[i] = fs;
                active[i] = fs;
                
                
                if (f.mState > Fragment.INITIALIZING && fs.mSavedFragmentState == null) {
                if (f.mState > Fragment.INITIALIZING && fs.mSavedFragmentState == null) {
                    if (mStateBundle == null) {
                    fs.mSavedFragmentState = saveFragmentBasicState(f);
                        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);
                        }
                    }


                    if (f.mTarget != null) {
                    if (f.mTarget != null) {
                        if (f.mTarget.mIndex < 0) {
                        if (f.mTarget.mIndex < 0) {
+3 −0
Original line number Original line Diff line number Diff line
@@ -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);
        return creator.createFromParcel(this);
    }
    }


Loading