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

Commit d1d4d9cb authored by Adam Powell's avatar Adam Powell
Browse files

Eagerly update fragment state when moving between states

As seen in frameworks/support!

Previously we would not set a fragment's new state until the move to a
new target state was fully complete. This causes problems when other
parts of the fragment manager infrastructure (such as lazily
initializing a child fragment manager) read that state while we're
dispatching a state change call to a fragment.

In this situation, adding a child fragment and then calling
executePendingTransactions on the child FragmentManager would not have
the intended effect, as the child FragmentManager would still be in
state INITIALIZING. The expected lifecycle callbacks to the child
fragment would then occur later.

Fix this by updating the fragment state as we go through each phase of
moveToState before we dispatch to the associated onState method,
matching our usual pattern of invoking onFoo methods after foo has
occurred. Delete the redundant resumed field as we now can use the
state directly.

Bug 25019275

Change-Id: I97fe45578d59ab643c9779eaeb475a331e446335
parent 7c132d82
Loading
Loading
Loading
Loading
+9 −6
Original line number Diff line number Diff line
@@ -409,9 +409,6 @@ public class Fragment implements ComponentCallbacks2, OnCreateContextMenuListene
    // If set this fragment is being removed from its activity.
    boolean mRemoving;

    // True if the fragment is in the resumed state.
    boolean mResumed;

    // Set to true if this fragment was instantiated from a layout file.
    boolean mFromLayout;

@@ -928,7 +925,7 @@ public class Fragment implements ComponentCallbacks2, OnCreateContextMenuListene
     * for the duration of {@link #onResume()} and {@link #onPause()} as well.
     */
    final public boolean isResumed() {
        return mResumed;
        return mState >= RESUMED;
    }

    /**
@@ -1630,7 +1627,6 @@ public class Fragment implements ComponentCallbacks2, OnCreateContextMenuListene
        mWho = null;
        mAdded = false;
        mRemoving = false;
        mResumed = false;
        mFromLayout = false;
        mInLayout = false;
        mRestored = false;
@@ -2113,7 +2109,6 @@ public class Fragment implements ComponentCallbacks2, OnCreateContextMenuListene
        writer.print(" mBackStackNesting="); writer.println(mBackStackNesting);
        writer.print(prefix); writer.print("mAdded="); writer.print(mAdded);
        writer.print(" mRemoving="); writer.print(mRemoving);
        writer.print(" mResumed="); writer.print(mResumed);
        writer.print(" mFromLayout="); writer.print(mFromLayout);
        writer.print(" mInLayout="); writer.println(mInLayout);
        writer.print(prefix); writer.print("mHidden="); writer.print(mHidden);
@@ -2208,6 +2203,7 @@ public class Fragment implements ComponentCallbacks2, OnCreateContextMenuListene
        if (mChildFragmentManager != null) {
            mChildFragmentManager.noteStateNotSaved();
        }
        mState = CREATED;
        mCalled = false;
        onCreate(savedInstanceState);
        if (!mCalled) {
@@ -2238,6 +2234,7 @@ public class Fragment implements ComponentCallbacks2, OnCreateContextMenuListene
        if (mChildFragmentManager != null) {
            mChildFragmentManager.noteStateNotSaved();
        }
        mState = ACTIVITY_CREATED;
        mCalled = false;
        onActivityCreated(savedInstanceState);
        if (!mCalled) {
@@ -2254,6 +2251,7 @@ public class Fragment implements ComponentCallbacks2, OnCreateContextMenuListene
            mChildFragmentManager.noteStateNotSaved();
            mChildFragmentManager.execPendingActions();
        }
        mState = STARTED;
        mCalled = false;
        onStart();
        if (!mCalled) {
@@ -2273,6 +2271,7 @@ public class Fragment implements ComponentCallbacks2, OnCreateContextMenuListene
            mChildFragmentManager.noteStateNotSaved();
            mChildFragmentManager.execPendingActions();
        }
        mState = RESUMED;
        mCalled = false;
        onResume();
        if (!mCalled) {
@@ -2389,6 +2388,7 @@ public class Fragment implements ComponentCallbacks2, OnCreateContextMenuListene
        if (mChildFragmentManager != null) {
            mChildFragmentManager.dispatchPause();
        }
        mState = STARTED;
        mCalled = false;
        onPause();
        if (!mCalled) {
@@ -2401,6 +2401,7 @@ public class Fragment implements ComponentCallbacks2, OnCreateContextMenuListene
        if (mChildFragmentManager != null) {
            mChildFragmentManager.dispatchStop();
        }
        mState = STOPPED;
        mCalled = false;
        onStop();
        if (!mCalled) {
@@ -2428,6 +2429,7 @@ public class Fragment implements ComponentCallbacks2, OnCreateContextMenuListene
        if (mChildFragmentManager != null) {
            mChildFragmentManager.dispatchDestroyView();
        }
        mState = CREATED;
        mCalled = false;
        onDestroyView();
        if (!mCalled) {
@@ -2443,6 +2445,7 @@ public class Fragment implements ComponentCallbacks2, OnCreateContextMenuListene
        if (mChildFragmentManager != null) {
            mChildFragmentManager.dispatchDestroy();
        }
        mState = INITIALIZING;
        mCalled = false;
        onDestroy();
        if (!mCalled) {
+7 −3
Original line number Diff line number Diff line
@@ -1004,7 +1004,6 @@ final class FragmentManagerImpl extends FragmentManager implements LayoutInflate
                case Fragment.STARTED:
                    if (newState > Fragment.STARTED) {
                        if (DEBUG) Log.v(TAG, "moveto RESUMED: " + f);
                        f.mResumed = true;
                        f.performResume();
                        // Get rid of this in case we saved it and never needed it.
                        f.mSavedFragmentState = null;
@@ -1017,7 +1016,6 @@ final class FragmentManagerImpl extends FragmentManager implements LayoutInflate
                    if (newState < Fragment.RESUMED) {
                        if (DEBUG) Log.v(TAG, "movefrom RESUMED: " + f);
                        f.performPause();
                        f.mResumed = false;
                    }
                case Fragment.STARTED:
                    if (newState < Fragment.STARTED) {
@@ -1096,6 +1094,8 @@ final class FragmentManagerImpl extends FragmentManager implements LayoutInflate
                            if (DEBUG) Log.v(TAG, "movefrom CREATED: " + f);
                            if (!f.mRetaining) {
                                f.performDestroy();
                            } else {
                                f.mState = Fragment.INITIALIZING;
                            }

                            f.mCalled = false;
@@ -1119,8 +1119,12 @@ final class FragmentManagerImpl extends FragmentManager implements LayoutInflate
            }
        }
        
        if (f.mState != newState) {
            Log.w(TAG, "moveToState: Fragment state for " + f + " not updated inline; "
                    + "expected state " + newState + " found " + f.mState);
            f.mState = newState;
        }
    }
    
    void moveToState(Fragment f) {
        moveToState(f, mCurState, 0, 0, false);