Fragment在生命周期中是如何走到onCreateView的(一)

最近遇到了一个Crash,于是想探究一下Fragment在onCreateView之前都干了什么?生命周期是如何跟Activity同步的?Fragment的视图又是如何添加到布局中的?
一步一步来探究。

以API 24为例

从一个简单的调用开始:

FragmentManager fragmentManager = getSupportFragmentManager();
Fragment fragment = QrGenerateFragment.newInstance("a", "b");
fragmentManager.beginTransaction()
        .replace(R.id.container, fragment)
        .commitAllowingStateLoss();

这里涉及到了几个类:FragmentManagerFragmentManagerImplFragmentTransactionBackStackRecord

先看beginTransaction

FragmentManager.java

@Override
public FragmentTransaction beginTransaction() {
    return new BackStackRecord(this);
}

其实是创建了一个BackStackRecord。从字面意思理解,就是回退栈的记录。
同时将FragmentManager的实例传给BackStackRecord

public BackStackRecord(FragmentManagerImpl manager) {
    mManager = manager;
}

然后是replace(R.id.container, fragment)

FragmentTransaction.java

@Override
public FragmentTransaction replace(int containerViewId, Fragment fragment) {
    return replace(containerViewId, fragment, null);
}

@Override
public FragmentTransaction replace(int containerViewId, Fragment fragment, String tag) {
    if (containerViewId == 0) {
        throw new IllegalArgumentException("Must use non-zero containerViewId");
    }

    doAddOp(containerViewId, fragment, tag, OP_REPLACE);
    return this;
}

传入一个ViewGroup的id,fragment实例,之后,tag设置为null

这里OP_REPLACE是代表什么操作:

static final int OP_NULL = 0;
static final int OP_ADD = 1;
static final int OP_REPLACE = 2;
static final int OP_REMOVE = 3;
static final int OP_HIDE = 4;
static final int OP_SHOW = 5;
static final int OP_DETACH = 6;
static final int OP_ATTACH = 7;

这里传的是OP_REPLACE,
如果是add的方式,就是OP_ADD

然后来看一下doAddOp

private void doAddOp(int containerViewId, Fragment fragment, String tag, int opcmd) {
    final Class fragmentClass = fragment.getClass();
    final int modifiers = fragmentClass.getModifiers();

     // 一开始是进行一些状态的判断
    if (fragmentClass.isAnonymousClass() || !Modifier.isPublic(modifiers)
            || (fragmentClass.isMemberClass() && !Modifier.isStatic(modifiers))) {
        throw new IllegalStateException("Fragment " + fragmentClass.getCanonicalName()
                + " must be a public static class to be  properly recreated from"
                + " instance state.");
    }

     // 然后给fragment的manager赋值
    fragment.mFragmentManager = mManager;

     // 判断的tag的一致性,如果tag不一致,就报错
    if (tag != null) {
        if (fragment.mTag != null && !tag.equals(fragment.mTag)) {
            throw new IllegalStateException("Can't change tag of fragment "
                    + fragment + ": was " + fragment.mTag
                    + " now " + tag);
        }
        fragment.mTag = tag;
    }

    if (containerViewId != 0) {
          // View.NO_ID是-1
        if (containerViewId == View.NO_ID) {
            throw new IllegalArgumentException("Can't add fragment "
                    + fragment + " with tag " + tag + " to container view with no id");
        }
          // fragmentId跟containerViewId不一致也报错,应该是之前有在其他的container里用过。
        if (fragment.mFragmentId != 0 && fragment.mFragmentId != containerViewId) {
            throw new IllegalStateException("Can't change container ID of fragment "
                    + fragment + ": was " + fragment.mFragmentId
                    + " now " + containerViewId);
        }
          // 这里可以看出,会把containerViewId赋值给fragmentId
        fragment.mContainerId = fragment.mFragmentId = containerViewId;
    }

    Op op = new Op();
    op.cmd = opcmd;
    op.fragment = fragment;
    addOp(op);
}

Op是一个回退栈存储内容

static final class Op {
    Op next;
    Op prev;
    int cmd;
    Fragment fragment;
    int enterAnim;
    int exitAnim;
    int popEnterAnim;
    int popExitAnim;
    ArrayList removed;
}

用于双向链表结构,Op包括上一个,下一个,还有动画参数等

void addOp(Op op) {
    if (mHead == null) {
        mHead = mTail = op;
    } else {
        op.prev = mTail;
        mTail.next = op;
        mTail = op;
    }
    op.enterAnim = mEnterAnim;
    op.exitAnim = mExitAnim;
    op.popEnterAnim = mPopEnterAnim;
    op.popExitAnim = mPopExitAnim;
    mNumOp++;
}

然后把新的Op加到链表中

这里replace就看完了.

下面是commitAllowingStateLoss

在BackStackRecord中

/**
* Entry of an operation on the fragment back stack.
*/
final class BackStackRecord extends FragmentTransaction implements
  FragmentManager.BackStackEntry, Runnable {

BackStackRecord是继承自FragmentTransaction的,并且实现了Runnable接口

@Override
public int commit() {
    return commitInternal(false);
}

@Override
public int commitAllowingStateLoss() {
    return commitInternal(true);
}

int commitInternal(boolean allowStateLoss) {
    if (mCommitted) throw new IllegalStateException("commit already called");
    if (FragmentManagerImpl.DEBUG) {
        Log.v(TAG, "Commit: " + this);
        LogWriter logw = new LogWriter(TAG);
        PrintWriter pw = new PrintWriter(logw);
        dump("  ", null, pw, null);
    }
    mCommitted = true;
    if (mAddToBackStack) {
          // 如果之前添加到回退栈里,会分配一个id,这里暂时不深究
        mIndex = mManager.allocBackStackIndex(this);
    } else {
        mIndex = -1;
    }

     // 把BackStackRecoed实例传入
    mManager.enqueueAction(this, allowStateLoss);
    return mIndex;
}

FragmentManager

/**
* Adds an action to the queue of pending actions.
*
* @param action the action to add
* @param allowStateLoss whether to allow loss of state information
* @throws IllegalStateException if the activity has been destroyed
*/
public void enqueueAction(Runnable action, boolean allowStateLoss) {
    if (!allowStateLoss) {
        checkStateLoss();
    }
    synchronized (this) {
        if (mDestroyed || mHost == null) {
            throw new IllegalStateException("Activity has been destroyed");
        }
        if (mPendingActions == null) {
            mPendingActions = new ArrayList();
        }
        mPendingActions.add(action);
        if (mPendingActions.size() == 1) {
            mHost.getHandler().removeCallbacks(mExecCommit);
            mHost.getHandler().post(mExecCommit);
        }
    }
}

action就是上面的BackStackRecoed实例,是一个Runnable.
里面会进行一系列的判断,最终会调用handler.post(mExecCommit)
mExecCommit是

Runnable mExecCommit = new Runnable() {
    @Override
    public void run() {
        execPendingActions();
    }
};

/**
* Only call from main thread!
*/
public boolean execPendingActions() {
    if (mExecutingActions) {
        throw new IllegalStateException("FragmentManager is already executing transactions");
    }

    if (Looper.myLooper() != mHost.getHandler().getLooper()) {
        throw new IllegalStateException("Must be called from main thread of fragment host");
    }

    boolean didSomething = false;

    while (true) {
        int numActions;

        synchronized (this) {
            if (mPendingActions == null || mPendingActions.size() == 0) {
                break;
            }

            numActions = mPendingActions.size();
            if (mTmpActions == null || mTmpActions.length < numActions) {
                mTmpActions = new Runnable[numActions];
            }
            mPendingActions.toArray(mTmpActions);
            mPendingActions.clear();
            mHost.getHandler().removeCallbacks(mExecCommit);
        }

        mExecutingActions = true;

          // 前面一大堆的处理,这里终于开始run了
        for (int i=0; i

moveToState

doPendingDeferredStart()本来是不准备去深究他的,但是在跟进的时候看到了moveToState(f, mCurState, 0, 0, false),应该是生命周期的转换
moveToState代码太多了,就是生命周期的转换逻辑,类似状态机

void moveToState(Fragment f, int newState, int transit, int transitionStyle,
        boolean keepActive) {
    // Fragments that are not currently added will sit in the onCreate() state.
    if ((!f.mAdded || f.mDetached) && newState > Fragment.CREATED) {
        newState = Fragment.CREATED;
    }
    if (f.mRemoving && newState > f.mState) {
        // While removing a fragment, we can't change it to a higher state.
        newState = f.mState;
    }
    // Defer start if requested; don't allow it to move to STARTED or higher
    // if it's not already started.
    if (f.mDeferStart && f.mState < Fragment.STARTED && newState > Fragment.STOPPED) {
        newState = Fragment.STOPPED;
    }
    if (f.mState < newState) {
        // For fragments that are created from a layout, when restoring from
        // state we don't want to allow them to be created until they are
        // being reloaded from the layout.
        if (f.mFromLayout && !f.mInLayout) {
            return;
        }
        if (f.mAnimatingAway != null) {
            // The fragment is currently being animated...  but!  Now we
            // want to move our state back up.  Give up on waiting for the
            // animation, move to whatever the final state should be once
            // the animation is done, and then we can proceed from there.
            f.mAnimatingAway = null;
            moveToState(f, f.mStateAfterAnimating, 0, 0, true);
        }
        switch (f.mState) {
            case Fragment.INITIALIZING:
                if (DEBUG) Log.v(TAG, "moveto CREATED: " + f);
                if (f.mSavedFragmentState != null) {
                    f.mSavedFragmentState.setClassLoader(mHost.getContext().getClassLoader());
                    f.mSavedViewState = f.mSavedFragmentState.getSparseParcelableArray(
                            FragmentManagerImpl.VIEW_STATE_TAG);
                    f.mTarget = getFragment(f.mSavedFragmentState,
                            FragmentManagerImpl.TARGET_STATE_TAG);
                    if (f.mTarget != null) {
                        f.mTargetRequestCode = f.mSavedFragmentState.getInt(
                                FragmentManagerImpl.TARGET_REQUEST_CODE_STATE_TAG, 0);
                    }
                    f.mUserVisibleHint = f.mSavedFragmentState.getBoolean(
                            FragmentManagerImpl.USER_VISIBLE_HINT_TAG, true);
                    if (!f.mUserVisibleHint) {
                        f.mDeferStart = true;
                        if (newState > Fragment.STOPPED) {
                            newState = Fragment.STOPPED;
                        }
                    }
                }
                f.mHost = mHost;
                f.mParentFragment = mParent;
                f.mFragmentManager = mParent != null
                        ? mParent.mChildFragmentManager : mHost.getFragmentManagerImpl();
                f.mCalled = false;
                    // onAttach在这里
                f.onAttach(mHost.getContext());
                if (!f.mCalled) {
                    throw new SuperNotCalledException("Fragment " + f
                            + " did not call through to super.onAttach()");
                }
                if (f.mParentFragment == null) {
                    mHost.onAttachFragment(f);
                } else {
                    f.mParentFragment.onAttachFragment(f);
                }

                if (!f.mRetaining) {
                    f.performCreate(f.mSavedFragmentState);
                } else {
                    f.restoreChildFragmentState(f.mSavedFragmentState);
                    f.mState = Fragment.CREATED;
                }
                f.mRetaining = false;
                if (f.mFromLayout) {
                    // For fragments that are part of the content view
                    // layout, we need to instantiate the view immediately
                    // and the inflater will take care of adding it.

                    // 这就是调用onCreateView的地方
                    f.mView = f.performCreateView(f.getLayoutInflater(
                            f.mSavedFragmentState), null, f.mSavedFragmentState);
                    if (f.mView != null) {
                        f.mInnerView = f.mView;
                        if (Build.VERSION.SDK_INT >= 11) {
                            ViewCompat.setSaveFromParentEnabled(f.mView, false);
                        } else {
                            f.mView = NoSaveStateFrameLayout.wrap(f.mView);
                        }
                        if (f.mHidden) f.mView.setVisibility(View.GONE);
                        f.onViewCreated(f.mView, f.mSavedFragmentState);
                    } else {
                        f.mInnerView = null;
                    }
                }
            case Fragment.CREATED:
                if (newState > Fragment.CREATED) {
                    if (DEBUG) Log.v(TAG, "moveto ACTIVITY_CREATED: " + f);
                    if (!f.mFromLayout) {
                        ViewGroup container = null;
                        if (f.mContainerId != 0) {
                            if (f.mContainerId == View.NO_ID) {
                                throwException(new IllegalArgumentException(
                                        "Cannot create fragment "
                                                + f
                                                + " for a container view with no id"));
                            }
                            container = (ViewGroup) mContainer.onFindViewById(f.mContainerId);
                            if (container == null && !f.mRestored) {
                                String resName;
                                try {
                                    resName = f.getResources().getResourceName(f.mContainerId);
                                } catch (NotFoundException e) {
                                    resName = "unknown";
                                }
                                throwException(new IllegalArgumentException(
                                        "No view found for id 0x"
                                        + Integer.toHexString(f.mContainerId) + " ("
                                        + resName
                                        + ") for fragment " + f));
                            }
                        }
                        f.mContainer = container;
                        f.mView = f.performCreateView(f.getLayoutInflater(
                                f.mSavedFragmentState), container, f.mSavedFragmentState);
                        if (f.mView != null) {
                            f.mInnerView = f.mView;
                            if (Build.VERSION.SDK_INT >= 11) {
                                ViewCompat.setSaveFromParentEnabled(f.mView, false);
                            } else {
                                f.mView = NoSaveStateFrameLayout.wrap(f.mView);
                            }
                            if (container != null) {
                                Animation anim = loadAnimation(f, transit, true,
                                        transitionStyle);
                                if (anim != null) {
                                    setHWLayerAnimListenerIfAlpha(f.mView, anim);
                                    f.mView.startAnimation(anim);
                                }
                                container.addView(f.mView);
                            }
                            if (f.mHidden) f.mView.setVisibility(View.GONE);
                            f.onViewCreated(f.mView, f.mSavedFragmentState);
                        } else {
                            f.mInnerView = null;
                        }
                    }

                    f.performActivityCreated(f.mSavedFragmentState);
                    if (f.mView != null) {
                        f.restoreViewState(f.mSavedFragmentState);
                    }
                    f.mSavedFragmentState = null;
                }
            case Fragment.ACTIVITY_CREATED:
                if (newState > Fragment.ACTIVITY_CREATED) {
                    f.mState = Fragment.STOPPED;
                }
            case Fragment.STOPPED:
                if (newState > Fragment.STOPPED) {
                    if (DEBUG) Log.v(TAG, "moveto STARTED: " + f);
                    f.performStart();
                }
            case Fragment.STARTED:
                if (newState > Fragment.STARTED) {
                    if (DEBUG) Log.v(TAG, "moveto RESUMED: " + f);
                    f.performResume();
                    f.mSavedFragmentState = null;
                    f.mSavedViewState = null;
                }
        }
    } else if (f.mState > newState) {
        switch (f.mState) {
            case Fragment.RESUMED:
                if (newState < Fragment.RESUMED) {
                    if (DEBUG) Log.v(TAG, "movefrom RESUMED: " + f);
                    f.performPause();
                }
            case Fragment.STARTED:
                if (newState < Fragment.STARTED) {
                    if (DEBUG) Log.v(TAG, "movefrom STARTED: " + f);
                    f.performStop();
                }
            case Fragment.STOPPED:
                if (newState < Fragment.STOPPED) {
                    if (DEBUG) Log.v(TAG, "movefrom STOPPED: " + f);
                    f.performReallyStop();
                }
            case Fragment.ACTIVITY_CREATED:
                if (newState < Fragment.ACTIVITY_CREATED) {
                    if (DEBUG) Log.v(TAG, "movefrom ACTIVITY_CREATED: " + f);
                    if (f.mView != null) {
                        // Need to save the current view state if not
                        // done already.
                        if (mHost.onShouldSaveFragmentState(f) && f.mSavedViewState == null) {
                            saveFragmentViewState(f);
                        }
                    }
                    f.performDestroyView();
                    if (f.mView != null && f.mContainer != null) {
                        Animation anim = null;
                        if (mCurState > Fragment.INITIALIZING && !mDestroyed) {
                            anim = loadAnimation(f, transit, false,
                                    transitionStyle);
                        }
                        if (anim != null) {
                            final Fragment fragment = f;
                            f.mAnimatingAway = f.mView;
                            f.mStateAfterAnimating = newState;
                            final View viewToAnimate = f.mView;
                            anim.setAnimationListener(new AnimateOnHWLayerIfNeededListener(
                                    viewToAnimate, anim) {
                                @Override
                                public void onAnimationEnd(Animation animation) {
                                    super.onAnimationEnd(animation);
                                    if (fragment.mAnimatingAway != null) {
                                        fragment.mAnimatingAway = null;
                                        moveToState(fragment, fragment.mStateAfterAnimating,
                                                0, 0, false);
                                    }
                                }
                            });
                            f.mView.startAnimation(anim);
                        }
                        f.mContainer.removeView(f.mView);
                    }
                    f.mContainer = null;
                    f.mView = null;
                    f.mInnerView = null;
                }
            case Fragment.CREATED:
                if (newState < Fragment.CREATED) {
                    if (mDestroyed) {
                        if (f.mAnimatingAway != null) {
                            // The fragment's containing activity is
                            // being destroyed, but this fragment is
                            // currently animating away.  Stop the
                            // animation right now -- it is not needed,
                            // and we can't wait any more on destroying
                            // the fragment.
                            View v = f.mAnimatingAway;
                            f.mAnimatingAway = null;
                            v.clearAnimation();
                        }
                    }
                    if (f.mAnimatingAway != null) {
                        // We are waiting for the fragment's view to finish
                        // animating away.  Just make a note of the state
                        // the fragment now should move to once the animation
                        // is done.
                        f.mStateAfterAnimating = newState;
                        newState = Fragment.CREATED;
                    } else {
                        if (DEBUG) Log.v(TAG, "movefrom CREATED: " + f);
                        if (!f.mRetaining) {
                            f.performDestroy();
                        } else {
                            f.mState = Fragment.INITIALIZING;
                        }

                        f.performDetach();
                        if (!keepActive) {
                            if (!f.mRetaining) {
                                makeInactive(f);
                            } else {
                                f.mHost = null;
                                f.mParentFragment = null;
                                f.mFragmentManager = null;
                            }
                        }
                    }
                }
        }
    }

    if (f.mState != newState) {
        Log.w(TAG, "moveToState: Fragment state for " + f + " not updated inline; "
                + "expected state " + newState + " found " + f.mState);
        f.mState = newState;
    }
}

而state

static final int INITIALIZING = 0;    // Not yet created.
static final int CREATED = 1;          // Created.
static final int ACTIVITY_CREATED = 2; // The activity has finished its creation.
static final int STOPPED = 3;          // Fully created, not started.
static final int STARTED = 4;          // Created and started, not resumed.
static final int RESUMED = 5;          // Created started and resumed.

这里可以看到从0~5分别对应了Fragmetn从开始到展示的几个生命周期状态,各个生命周期就是在这里进行流转的,暂不细究。

然后下面是BackStackRecoed的run

@Override
public void run() {
    if (FragmentManagerImpl.DEBUG) Log.v(TAG, "Run: " + this);

    if (mAddToBackStack) {
        if (mIndex < 0) {
            throw new IllegalStateException("addToBackStack() called after commit()");
        }
    }

    bumpBackStackNesting(1);

    TransitionState state = null;
    SparseArray firstOutFragments = null;
    SparseArray lastInFragments = null;
    if (SUPPORTS_TRANSITIONS && mManager.mCurState >= Fragment.CREATED) {
        firstOutFragments = new SparseArray();
        lastInFragments = new SparseArray();

        calculateFragments(firstOutFragments, lastInFragments);

        state = beginTransition(firstOutFragments, lastInFragments, false);
    }

    int transitionStyle = state != null ? 0 : mTransitionStyle;
    int transition = state != null ? 0 : mTransition;
    Op op = mHead;
     // 从头到尾开始执行Op
    while (op != null) {
        int enterAnim = state != null ? 0 : op.enterAnim;
        int exitAnim = state != null ? 0 : op.exitAnim;
        switch (op.cmd) {
            case OP_ADD: {
                Fragment f = op.fragment;
                f.mNextAnim = enterAnim;
                mManager.addFragment(f, false);
            } break;
            case OP_REPLACE: {
               // 取出fragment和containerId
                Fragment f = op.fragment;
                int containerId = f.mContainerId;

               // mAdded是{ArrayList mAdded;}
                if (mManager.mAdded != null) {
                    for (int i = mManager.mAdded.size() - 1; i >= 0; i--) {
                         // 取出顶端的fragment
                        Fragment old = mManager.mAdded.get(i);
                        if (FragmentManagerImpl.DEBUG) Log.v(TAG,
                                "OP_REPLACE: adding=" + f + " old=" + old);
                         // 判断一下containerId是否一致
                        if (old.mContainerId == containerId) {
                            if (old == f) {
                                op.fragment = f = null;
                            } else {
                                if (op.removed == null) {
                                    op.removed = new ArrayList();
                                }
                                   // 把old放到op的removed数组里面
                                op.removed.add(old);
                                old.mNextAnim = exitAnim;
                                if (mAddToBackStack) {
                                    old.mBackStackNesting += 1;
                                    if (FragmentManagerImpl.DEBUG) Log.v(TAG, "Bump nesting of "
                                            + old + " to " + old.mBackStackNesting);
                                }
                                   //然后把old从mManager中remove掉
                                mManager.removeFragment(old, transition, transitionStyle);
                            }
                        }
                    }
                }
                if (f != null) {
                    f.mNextAnim = enterAnim;
                    // 最后mManager添加新的fragment
                    mManager.addFragment(f, false);
                }
            } break;
            case OP_REMOVE: {
                Fragment f = op.fragment;
                f.mNextAnim = exitAnim;
                mManager.removeFragment(f, transition, transitionStyle);
            } break;
            case OP_HIDE: {
                Fragment f = op.fragment;
                f.mNextAnim = exitAnim;
                mManager.hideFragment(f, transition, transitionStyle);
            } break;
            case OP_SHOW: {
                Fragment f = op.fragment;
                f.mNextAnim = enterAnim;
                mManager.showFragment(f, transition, transitionStyle);
            } break;
            case OP_DETACH: {
                Fragment f = op.fragment;
                f.mNextAnim = exitAnim;
                mManager.detachFragment(f, transition, transitionStyle);
            } break;
            case OP_ATTACH: {
                Fragment f = op.fragment;
                f.mNextAnim = enterAnim;
                mManager.attachFragment(f, transition, transitionStyle);
            } break;
            default: {
                throw new IllegalArgumentException("Unknown cmd: " + op.cmd);
            }
        }

        op = op.next;
    }

    mManager.moveToState(mManager.mCurState, transition, transitionStyle, true);

    if (mAddToBackStack) {
        mManager.addBackStackState(this);
    }
}

下面看一下add和remove

public void addFragment(Fragment fragment, boolean moveToStateNow) {
    if (mAdded == null) {
        mAdded = new ArrayList();
    }
    if (DEBUG) Log.v(TAG, "add: " + fragment);
     // 分配一个index
    makeActive(fragment);
    if (!fragment.mDetached) {
        if (mAdded.contains(fragment)) {
            throw new IllegalStateException("Fragment already added: " + fragment);
        }
          // 添加到mAdd数组中
        mAdded.add(fragment);
        fragment.mAdded = true;
        fragment.mRemoving = false;
        if (fragment.mHasMenu && fragment.mMenuVisible) {
               // 处理一下menu标识
            mNeedMenuInvalidate = true;
        }
        if (moveToStateNow) {
               // 然后就是moveToState啦,这里就进入了fragment相应的生命周期
            moveToState(fragment);
        }
    }
}


public void removeFragment(Fragment fragment, int transition, int transitionStyle) {
    if (DEBUG) Log.v(TAG, "remove: " + fragment + " nesting=" + fragment.mBackStackNesting);
    final boolean inactive = !fragment.isInBackStack();
    if (!fragment.mDetached || inactive) {
        if (mAdded != null) {
            mAdded.remove(fragment);
        }
        if (fragment.mHasMenu && fragment.mMenuVisible) {
            mNeedMenuInvalidate = true;
        }
        fragment.mAdded = false;
        fragment.mRemoving = true;
        moveToState(fragment, inactive ? Fragment.INITIALIZING : Fragment.CREATED,
                transition, transitionStyle, false);
    }
}

小结:
1. FragmentManager创建了一个BackStackRecord
2. 生成一个Op,放到一个链表中,其实这是一个事务
3. commit,依次执行事务中的Op
4. Op中取出fragment,根据cmd执行相应操作,最后执行到moveToState,一步一步进行生命周期的流转

你可能感兴趣的:(Android)