Fragment启动过程,从getFragmentManager开始

概述

时至今日,Fragment已经成为Android开发中应用最广泛的方案了,几乎每一个APP都离不开它的影子。为了更深入的理解其中原理,我们从Fragment中源码开始分析。这里我们选择V4包中的Fragment来进行分析。
为了在低版本中使用Fragment需要用到V4兼容包,我们首先需要继承V4包中FragmentActivity,它提供了操作Fragment的一些方法。如果有对V4不太了解的同学,网上关于V4的说明非常丰富,可以自行查阅。

FragmentActivity初始化

如上在使用Fragment之前,我们首先继承FragmentActivity类。我们知道当一个Activity开启后,一般都会在onCreate方法中进行一些初始化操作。我们可以先看onCreate方法。
FragmentActivity#onCreate

.....
final FragmentController mFragments = FragmentController.createController(new HostCallbacks());
.....

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {

    //step 1:
    mFragments.attachHost(null /*parent*/);

    super.onCreate(savedInstanceState);

    NonConfigurationInstances nc =
            (NonConfigurationInstances) getLastNonConfigurationInstance();
    if (nc != null) {
        mFragments.restoreLoaderNonConfig(nc.loaders);
    }
    if (savedInstanceState != null) {
        Parcelable p = savedInstanceState.getParcelable(FRAGMENTS_TAG);
        mFragments.restoreAllState(p, nc != null ? nc.fragments : null);

        // Check if there are any pending onActivityResult calls to descendent Fragments.
        if (savedInstanceState.containsKey(NEXT_CANDIDATE_REQUEST_INDEX_TAG)) {
            mNextCandidateRequestIndex =
                    savedInstanceState.getInt(NEXT_CANDIDATE_REQUEST_INDEX_TAG);
            int[] requestCodes = savedInstanceState.getIntArray(ALLOCATED_REQUEST_INDICIES_TAG);
            String[] fragmentWhos = savedInstanceState.getStringArray(REQUEST_FRAGMENT_WHO_TAG);
            if (requestCodes == null || fragmentWhos == null ||
                        requestCodes.length != fragmentWhos.length) {
                Log.w(TAG, "Invalid requestCode mapping in savedInstanceState.");
            } else {
                mPendingFragmentActivityResults = new SparseArrayCompat<>(requestCodes.length);
                for (int i = 0; i < requestCodes.length; i++) {
                    mPendingFragmentActivityResults.put(requestCodes[i], fragmentWhos[i]);
                }
            }
        }
    }

    if (mPendingFragmentActivityResults == null) {
        mPendingFragmentActivityResults = new SparseArrayCompat<>();
        mNextCandidateRequestIndex = 0;
    }

    //step 2:
    mFragments.dispatchCreate();
}

如上,我们知道mFragments是FragmentController类。该引用在FragmentActivity被加载时,会被初始化。我们来看对
FragmentController的介绍:

/**
 * Provides integration points with a {@link FragmentManager} for a fragment host.
 * <p>
 * It is the responsibility of the host to take care of the Fragment's lifecycle.
 * The methods provided by {@link FragmentController} are for that purpose.
 */

FragmentController提供了方法来负责管理Fragment的生命周期,分发给fragment host中的FragmentManager。继续来看下FragmentController内部的代码:

public class FragmentController {

    private final FragmentHostCallback<?> mHost;

    /**
     * Returns a {@link FragmentController}.
     */
    public static final FragmentController createController(FragmentHostCallback<?> callbacks) {
        return new FragmentController(callbacks);
    }

    private FragmentController(FragmentHostCallback<?> callbacks) {
        mHost = callbacks;
    }

    /**
     * Returns a {@link FragmentManager} for this controller.
     */
    public FragmentManager getSupportFragmentManager() {
        return mHost.getFragmentManagerImpl();
    }

    .....

    public void attachHost(Fragment parent) {
        mHost.mFragmentManager.attachController(
                mHost, mHost /*container*/, parent);
    }

    public View onCreateView(View parent, String name, Context context, AttributeSet attrs) {
        return mHost.mFragmentManager.onCreateView(parent, name, context, attrs);
    }

    public void dispatchCreate() {
        mHost.mFragmentManager.dispatchCreate();
    }

    .....
}

FragmentController是个单例的实现,内部持有一个FragmentHostCallback引用,外部在调用方法createController时,传入FragmentHostCallback参数(这里传递的是HostCallbacks对象),来创建一个FragmentController对象。
继续查看下FragmentHostCallback类:

public abstract class FragmentHostCallback<E> extends FragmentContainer {

    private final Activity mActivity;
    final Context mContext;
    private final Handler mHandler;
    final int mWindowAnimations;
    final FragmentManagerImpl mFragmentManager = new FragmentManagerImpl();
    /** The loader managers for individual fragments [i.e. Fragment#getLoaderManager()] */
    private SimpleArrayMap<String, LoaderManager> mAllLoaderManagers;
    /** Whether or not fragment loaders should retain their state */
    private boolean mRetainLoaders;
    /** The loader manger for the fragment host [i.e. Activity#getLoaderManager()] */
    private LoaderManagerImpl mLoaderManager;
    private boolean mCheckedForLoaderManager;
    /** Whether or not the fragment host loader manager was started */
    private boolean mLoadersStarted;

    public FragmentHostCallback(Context context, Handler handler, int windowAnimations) {
        this(context instanceof Activity ? (Activity) context : null, context, handler,windowAnimations);
    }

    FragmentHostCallback(FragmentActivity activity) {
        this(activity, activity /*context*/, activity.mHandler, 0 /*windowAnimations*/);
    }

    FragmentHostCallback(Activity activity, Context context, Handler handler,
            int windowAnimations) {
        mActivity = activity;
        mContext = context;
        mHandler = handler;
        mWindowAnimations = windowAnimations;
    }

    ......
}

我们来分析该类中持有的引用:

mActivity:当前Fragment中的宿主Activity

mContext:当前Fragment中的宿主Activity

mHandler:当前Fragment中的宿主Activity中的handler属性

以上都是通过新建FragmentHostCallback对象时,通过参数传递而来。
而我们看到该类中还实例化了一个FragmentManagerImpl对象,该对象是FragmentManager具体实现类,由它来管理Fragment的生命周期。稍后我们将详细分析这个类。

现在我们回到前面FragmentActivity中,再梳理一下流程。首先在加载FragmentActivity时,生成了FragmentController对象,这里以HostCallbacks作为FragmentHostCallback实现类,作为参数传入。到这一步就完成了FragmentHostCallback内部属性的初始化过程。

接着我们回到FragmentActivity的onCreate方法:

step 1: 执行mFragments.attachHost(null);

FragmentController#attachHost

public void attachHost(Fragment parent) {
    mHost.mFragmentManager.attachController(mHost, mHost /*container*/, parent);
}

这里的mHost,我们知道是HostCallbacks实例化对象。mFragmentManager的具体实现对象是FragmentManagerImpl,所以这里直接调用FragmentManagerImpl的方法:

FragmentManagerImpl#attachController

public void attachController(FragmentHostCallback host,
        FragmentContainer container, Fragment parent) {
    if (mHost != null) throw new IllegalStateException("Already attached");
    mHost = host;
    mContainer = container;
    mParent = parent;
}

这里方法中传递的参数分别是:

host:HostCallbacks对象

container:HostCallbacks对象

parent:null

从这里可以看出在执行mFragments.attachHost(null)时,就是将对象中的参数初始化。而这些对象之间的关系,如下:
image

step 2: 执行mFragments.dispatchCreate();
FragmentController#dispatchCreate

public void dispatchCreate() {
    mHost.mFragmentManager.dispatchCreate();
}

同样的执行的是FragmentManagerImpl中的方法:

FragmentManagerImpl#dispatchCreate

public void dispatchCreate() {
    mStateSaved = false;
    mExecutingActions = true;
    moveToState(Fragment.CREATED, false);
    mExecutingActions = false;
}

里面执行了一个重要的方法:moveToState,这个方法用来更改fragment manager中的当前状态。这里传入的参数值为:

newState = Fragment.CREATED

always = false

FragmentManagerImpl#moveToState

void moveToState(int newState, boolean always) {
    //判断宿主不能为空
    if (mHost == null && newState != Fragment.INITIALIZING) {
        throw new IllegalStateException("No activity");
    }
    // 与当前状态相同时,不处理
    if (!always && newState == mCurState) {
        return;
    }
    // 保存当前状态
    mCurState = newState;

    if (mActive != null) {
        boolean loadersRunning = false;

        // Must add them in the proper order. mActive fragments may be out of order
        if (mAdded != null) {
            final int numAdded = mAdded.size();
            for (int i = 0; i < numAdded; i++) {
                Fragment f = mAdded.get(i);
                moveFragmentToExpectedState(f);
                if (f.mLoaderManager != null) {
                    loadersRunning |= f.mLoaderManager.hasRunningLoaders();
                }
            }
        }

        // Now iterate through all active fragments. These will include those that are removed
        // and detached.
        final int numActive = mActive.size();
        for (int i = 0; i < numActive; i++) {
            Fragment f = mActive.get(i);
            if (f != null && (f.mRemoving || f.mDetached) && !f.mIsNewlyAdded) {
                moveFragmentToExpectedState(f);
                if (f.mLoaderManager != null) {
                    loadersRunning |= f.mLoaderManager.hasRunningLoaders();
                }
            }
        }

        if (!loadersRunning) {
            startPendingDeferredFragments();
        }

        if (mNeedMenuInvalidate && mHost != null && mCurState == Fragment.RESUMED) {
            mHost.onSupportInvalidateOptionsMenu();
            mNeedMenuInvalidate = false;
        }
    }
}

方法中保存当前状态为:Fragment.CREATED,初次加载时 mActive 属性为null,里面的代码将不会执行。
在这里补充说明一下,前面我们说过FragmentController提供了方法来负责管理Fragment的生命周期,用来将Activity的生命周期分发给fragment host中的FragmentManager,从而方便对Fragment的生命周期的管理。

我们可以看下FragmentActivity中的生命周期方法中执行的参数:

FragmentActivity

@Override
protected void onStart() {
    super.onStart();

    .....

    mFragments.dispatchStart();
    .....
}


@Override
protected void onPostResume() {
    super.onPostResume();
    mHandler.removeMessages(MSG_RESUME_PENDING);
    onResumeFragments();
    mFragments.execPendingActions();
}

protected void onResumeFragments() {
    mFragments.dispatchResume();
}

@Override
protected void onPause() {
    super.onPause();
    mResumed = false;
    if (mHandler.hasMessages(MSG_RESUME_PENDING)) {
        mHandler.removeMessages(MSG_RESUME_PENDING);
        onResumeFragments();
    }
    mFragments.dispatchPause();
}

@Override
protected void onStop() {
    super.onStop();

    mStopped = true;
    mHandler.sendEmptyMessage(MSG_REALLY_STOPPED);

    mFragments.dispatchStop();
}

@Override
protected void onDestroy() {
    super.onDestroy();

    doReallyStop(false);

    mFragments.dispatchDestroy();
    mFragments.doLoaderDestroy();
}

可以看出随着FragmentActivity中生命周期的变化,Fragment生命周期做出相应的改变。
我们再看看FragmentManager中,对应Fragment的生命周期的操作。

public void dispatchCreate() {
    mStateSaved = false;
    mExecutingActions = true;
    moveToState(Fragment.CREATED, false);
    mExecutingActions = false;
}

public void dispatchActivityCreated() {
    mStateSaved = false;
    mExecutingActions = true;
    moveToState(Fragment.ACTIVITY_CREATED, false);
    mExecutingActions = false;
}

public void dispatchStart() {
    mStateSaved = false;
    mExecutingActions = true;
    moveToState(Fragment.STARTED, false);
    mExecutingActions = false;
}

public void dispatchResume() {
    mStateSaved = false;
    mExecutingActions = true;
    moveToState(Fragment.RESUMED, false);
    mExecutingActions = false;
}

public void dispatchPause() {
    mExecutingActions = true;
    moveToState(Fragment.STARTED, false);
    mExecutingActions = false;
}

public void dispatchStop() {
    // See saveAllState() for the explanation of this.  We do this for
    // all platform versions, to keep our behavior more consistent between
    // them.
    mStateSaved = true;

    mExecutingActions = true;
    moveToState(Fragment.STOPPED, false);
    mExecutingActions = false;
}

public void dispatchReallyStop() {
    mExecutingActions = true;
    moveToState(Fragment.ACTIVITY_CREATED, false);
    mExecutingActions = false;
}

public void dispatchDestroyView() {
    mExecutingActions = true;
    moveToState(Fragment.CREATED, false);
    mExecutingActions = false;
}

public void dispatchDestroy() {
    mDestroyed = true;
    execPendingActions();
    mExecutingActions = true;
    moveToState(Fragment.INITIALIZING, false);
    mExecutingActions = false;
    mHost = null;
    mContainer = null;
    mParent = null;
}

上面完成了关键对象参数的初始化后,下面我们就来调用了。如果使用代码动态加载Fragment的话,我们一般执行下面代码:

Fragment fragment = new Fragment();  
.....

//step 1
FragmentManager manager = getSupportFragmentManager();  
//step 2
FragmentTransaction transaction = manager.beginTransaction();  
//step 3
transaction.add(R.id.fragment_container, fragment);  
//step 4
transaction.commit();  

step 1:

FragmentActivity#getSupportFragmentManager

public FragmentManager getSupportFragmentManager() {
    return mFragments.getSupportFragmentManager();
}

里面其实是执行:
FragmentController#getSupportFragmentManager

public FragmentManager getSupportFragmentManager() {
    return mHost.getFragmentManagerImpl();
}

这里我们知道获取之前初始化的FragmentManagerImpl的对象实例。

step 2:

执行的是FragmentManagerImpl中方法:

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

这里直接创建一个BackStackRecord实例对象,传入的参数是之前实例化的FragmentManagerImpl对象,此对象现在复制给BackStackRecord类内部的mManager属性。

由此可以BackStackRecord是FragmentTransaction的具体实现类。

step 3:

.....

static final class Op {
    int cmd;
    Fragment fragment;
    int enterAnim;
    int exitAnim;
    int popEnterAnim;
    int popExitAnim;
}

ArrayList<Op> mOps = new ArrayList<>();

......

@Override
public FragmentTransaction add(int containerViewId, Fragment fragment) {
    doAddOp(containerViewId, fragment, null, OP_ADD);
    return this;
}

private void doAddOp(int containerViewId, Fragment fragment, String tag, int opcmd) {
    final Class fragmentClass = fragment.getClass();
    final int modifiers = fragmentClass.getModifiers();
    // 判断fragmentClass 是否符合要求
    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.");
    }

    // 将mManager属性赋值给fragment中的 mFragmentManager
    fragment.mFragmentManager = mManager;

    // 如果tag不为空并且与fagment中当前mTag不相等,则赋值
    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;
    }

    // containerViewId 不为0 且与 fragment中的mFragmentId不相等事,则赋值。
    if (containerViewId != 0) {
        if (containerViewId == View.NO_ID) {
            throw new IllegalArgumentException("Can't add fragment "
                    + fragment + " with tag " + tag + " to container view with no id");
        }
        if (fragment.mFragmentId != 0 && fragment.mFragmentId != containerViewId) {
            throw new IllegalStateException("Can't change container ID of fragment "
                    + fragment + ": was " + fragment.mFragmentId
                    + " now " + containerViewId);
        }
        fragment.mContainerId = fragment.mFragmentId = containerViewId;
    }

    Op op = new Op();
    op.cmd = opcmd;
    op.fragment = fragment;
    addOp(op); //将fragment加入ArrayList集合中。
}

step 4:

BackStackRecord#commit

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

BackStackRecord#commitInternal

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);
        pw.close();
    }
    // 赋值,不能重复提交
    mCommitted = true;

    //判断是否加入返回栈
    if (mAddToBackStack) {
        mIndex = mManager.allocBackStackIndex(this);
    } else {
        mIndex = -1;
    }
    mManager.enqueueAction(this, allowStateLoss);
    return mIndex;
}

FragmentManagerImpl#enqueueAction

调用方法commit时,传入为false;

调用方法commitAllowingStateLoss时,传入为true;

public void enqueueAction(OpGenerator 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);
        scheduleCommit();
    }
}

使用commit方法提交时,会执行checkStateLoss方法来判断当前状态是否保存,我们来看下

FragmentManagerImpl#checkStateLoss

private void checkStateLoss() {
    //状态为true时,抛出异常
    if (mStateSaved) {
        throw new IllegalStateException(
                "Can not perform this action after onSaveInstanceState");
    }
    // 不为空时,抛出异常
    if (mNoTransactionsBecause != null) {
        throw new IllegalStateException(
                "Can not perform this action inside of " + mNoTransactionsBecause);
    }
}

主要来分析mStateSaved为true的情况:

1.执行saveAllState方法时,如果版本为HONEYCOMB(Android 3.0) 以上时,都会将mStateSaved设置为true。而这个方法在Activity中的onSaveInstanceState执行。

2.在执行dispatchStop时,mStateSaved状态也会被设置为true。而这个方法发生在Activity中的onStop回调。

上述两中情形下,不能执行commit的操作。

完成saveAllState状态判断之后,再来执行方法scheduleCommit:

FragmentManagerImpl#scheduleCommit

private void scheduleCommit() {
    synchronized (this) {
        boolean postponeReady =
                mPostponedTransactions != null && !mPostponedTransactions.isEmpty();
        boolean pendingReady = mPendingActions != null && mPendingActions.size() == 1;
        if (postponeReady || pendingReady) {
            mHost.getHandler().removeCallbacks(mExecCommit);
            mHost.getHandler().post(mExecCommit);
        }
    }
}

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

FragmentManagerImpl#execPendingActions

/**
 * Only call from main thread!
 */
public boolean execPendingActions() {

    //执行操作前的准备阶段
    ensureExecReady(true);

    boolean didSomething = false;
    while (generateOpsForPendingActions(mTmpRecords, mTmpIsPop)) {
        mExecutingActions = true;
        try {
            optimizeAndExecuteOps(mTmpRecords, mTmpIsPop);
        } finally {
            cleanupExec();
        }
        didSomething = true;
    }

    doPendingDeferredStart();

    return didSomething;
}

FragmentManagerImpl#ensureExecReady

private void ensureExecReady(boolean allowStateLoss) {
    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");
    }

    if (!allowStateLoss) {
        checkStateLoss();
    }

    if (mTmpRecords == null) {
        mTmpRecords = new ArrayList<>();
        mTmpIsPop = new ArrayList<>();
    }
    mExecutingActions = true;
    try {
        executePostponedTransaction(null, null);
    } finally {
        mExecutingActions = false;
    }
}

FragmentManagerImpl#executePostponedTransaction

private void executePostponedTransaction(ArrayList<BackStackRecord> records,ArrayList<Boolean> isRecordPop) {

    int numPostponed = mPostponedTransactions == null ? 0 : mPostponedTransactions.size();
    for (int i = 0; i < numPostponed; i++) {
        StartEnterTransitionListener listener = mPostponedTransactions.get(i);
        if (records != null && !listener.mIsBack) {
            int index = records.indexOf(listener.mRecord);
            if (index != -1 && isRecordPop.get(index)) {
                listener.cancelTransaction();
                continue;
            }
        }
        if (listener.isReady() || (records != null
                && listener.mRecord.interactsWith(records, 0, records.size()))) {
            mPostponedTransactions.remove(i);
            i--;
            numPostponed--;
            int index;
            if (records != null && !listener.mIsBack
                    && (index = records.indexOf(listener.mRecord)) != -1
                    && isRecordPop.get(index)) {
                // This is popping a postponed transaction
                listener.cancelTransaction();
            } else {
                listener.completeTransaction();
            }
        }
    }
}

FragmentManagerImpl#generateOpsForPendingActions

private boolean generateOpsForPendingActions(ArrayList<BackStackRecord> records,
        ArrayList<Boolean> isPop) {
    int numActions;
    synchronized (this) {
        if (mPendingActions == null || mPendingActions.size() == 0) {
            return false;
        }

        numActions = mPendingActions.size();
        for (int i = 0; i < numActions; i++) {
            mPendingActions.get(i).generateOps(records, isPop);
        }
        mPendingActions.clear();
        mHost.getHandler().removeCallbacks(mExecCommit);
    }
    return numActions > 0;
}

FragmentManagerImpl#optimizeAndExecuteOps

//优化回退栈操作,一个transaction被加入栈后,然后又被弹出,这个回退栈记录将被优化
private void optimizeAndExecuteOps(ArrayList<BackStackRecord> records,ArrayList<Boolean> isRecordPop) {

    if (records == null || records.isEmpty()) {
        return;
    }

    if (isRecordPop == null || records.size() != isRecordPop.size()) {
        throw new IllegalStateException("Internal error with the back stack records");
    }

    // Force start of any postponed transactions that interact with scheduled transactions:
    executePostponedTransaction(records, isRecordPop);

    final int numRecords = records.size();
    int startIndex = 0;
    for (int recordNum = 0; recordNum < numRecords; recordNum++) {
        final boolean canOptimize = records.get(recordNum).mAllowOptimization;
        if (!canOptimize) {
            // execute all previous transactions
            if (startIndex != recordNum) {
                executeOpsTogether(records, isRecordPop, startIndex, recordNum);
            }
            // execute all unoptimized pop operations together or one add operation
            int optimizeEnd = recordNum + 1;
            if (isRecordPop.get(recordNum)) {
                while (optimizeEnd < numRecords
                        && isRecordPop.get(optimizeEnd)
                        && !records.get(optimizeEnd).mAllowOptimization) {
                    optimizeEnd++;
                }
            }
            executeOpsTogether(records, isRecordPop, recordNum, optimizeEnd);
            startIndex = optimizeEnd;
            recordNum = optimizeEnd - 1;
        }
    }
    if (startIndex != numRecords) {
        executeOpsTogether(records, isRecordPop, startIndex, numRecords);
    }
}

FragmentManagerImpl#doPendingDeferredStart

void doPendingDeferredStart() {
    if (mHavePendingDeferredStart) {
        boolean loadersRunning = false;
        for (int i = 0; i < mActive.size(); i++) {
            Fragment f = mActive.get(i);
            if (f != null && f.mLoaderManager != null) {
                loadersRunning |= f.mLoaderManager.hasRunningLoaders();
            }
        }
        if (!loadersRunning) {
            mHavePendingDeferredStart = false;
            startPendingDeferredFragments();
        }
    }
}

FragmentManagerImpl#startPendingDeferredFragments

void startPendingDeferredFragments() {
    if (mActive == null) return;

    for (int i=0; i<mActive.size(); i++) {
        Fragment f = mActive.get(i);
        if (f != null) {
            performPendingDeferredStart(f);
        }
    }
}

上面代码中首先判断mActive中不为空,这个mActive是FragmentManager中用来保存Fragment。它在makeActive方法中初始化:

FragmentManagerImpl#makeActive

void makeActive(Fragment f) {
    if (f.mIndex >= 0) {
        return;
    }

    if (mAvailIndices == null || mAvailIndices.size() <= 0) {
        if (mActive == null) {
            mActive = new ArrayList<Fragment>();
        }
        f.setIndex(mActive.size(), mParent);
        mActive.add(f);

    } else {
        f.setIndex(mAvailIndices.remove(mAvailIndices.size()-1), mParent);
        mActive.set(f.mIndex, f);
    }
    if (DEBUG) Log.v(TAG, "Allocated fragment index " + f);
}

我们可以看到在addFragment方法中调用了makeActive方法:

FragmentManagerImpl#addFragment

public void addFragment(Fragment fragment, boolean moveToStateNow) {
    if (mAdded == null) {
        mAdded = new ArrayList<Fragment>();
    }
    if (DEBUG) Log.v(TAG, "add: " + fragment);
    makeActive(fragment);
    if (!fragment.mDetached) {
        if (mAdded.contains(fragment)) {
            throw new IllegalStateException("Fragment already added: " + fragment);
        }
        mAdded.add(fragment);
        fragment.mAdded = true;
        fragment.mRemoving = false;
        if (fragment.mView == null) {
            fragment.mHiddenChanged = false;
        }
        if (fragment.mHasMenu && fragment.mMenuVisible) {
            mNeedMenuInvalidate = true;
        }
        if (moveToStateNow) {
            moveToState(fragment);
        }
    }
}

继续查看的话,我们可以看到addFragment的调用是在FragmentManagerImpl的onCreateView方法中,而在前面可以知道这里的onCreateView方法是由FragmentController分发而来:

FragmentManagerImpl#onCreateView

@Override
public View onCreateView(View parent, String name, Context context, AttributeSet attrs) {
    if (!"fragment".equals(name)) {
        return null;
    }

    String fname = attrs.getAttributeValue(null, "class");
    TypedArray a =  context.obtainStyledAttributes(attrs, FragmentTag.Fragment);
    if (fname == null) {
        fname = a.getString(FragmentTag.Fragment_name);
    }
    int id = a.getResourceId(FragmentTag.Fragment_id, View.NO_ID);
    String tag = a.getString(FragmentTag.Fragment_tag);
    a.recycle();

    if (!Fragment.isSupportFragmentClass(mHost.getContext(), fname)) {
        // Invalid support lib fragment; let the device's framework handle it.
        // This will allow android.app.Fragments to do the right thing.
        return null;
    }

    int containerId = parent != null ? parent.getId() : 0;
    if (containerId == View.NO_ID && id == View.NO_ID && tag == null) {
        throw new IllegalArgumentException(attrs.getPositionDescription()
                + ": Must specify unique android:id, android:tag, or have a parent with an id for " + fname);
    }

    // If we restored from a previous state, we may already have
    // instantiated this fragment from the state and should use
    // that instance instead of making a new one.
    Fragment fragment = id != View.NO_ID ? findFragmentById(id) : null;
    if (fragment == null && tag != null) {
        fragment = findFragmentByTag(tag);
    }
    if (fragment == null && containerId != View.NO_ID) {
        fragment = findFragmentById(containerId);
    }

    if (FragmentManagerImpl.DEBUG) Log.v(TAG, "onCreateView: id=0x"
            + Integer.toHexString(id) + " fname=" + fname
            + " existing=" + fragment);
    if (fragment == null) {
        fragment = Fragment.instantiate(context, fname);
        fragment.mFromLayout = true;
        fragment.mFragmentId = id != 0 ? id : containerId;
        fragment.mContainerId = containerId;
        fragment.mTag = tag;
        fragment.mInLayout = true;
        fragment.mFragmentManager = this;
        fragment.mHost = mHost;
        fragment.onInflate(mHost.getContext(), attrs, fragment.mSavedFragmentState);
        addFragment(fragment, true);

    } else if (fragment.mInLayout) {
        // A fragment already exists and it is not one we restored from
        // previous state.
        throw new IllegalArgumentException(attrs.getPositionDescription()
                + ": Duplicate id 0x" + Integer.toHexString(id)
                + ", tag " + tag + ", or parent id 0x" + Integer.toHexString(containerId)
                + " with another fragment for " + fname);
    } else {
        // This fragment was retained from a previous instance; get it
        // going now.
        fragment.mInLayout = true;
        fragment.mHost = mHost;
        // If this fragment is newly instantiated (either right now, or
        // from last saved state), then give it the attributes to
        // initialize itself.
        if (!fragment.mRetaining) {
            fragment.onInflate(mHost.getContext(), attrs, fragment.mSavedFragmentState);
        }
    }

    // If we haven't finished entering the CREATED state ourselves yet,
    // push the inflated child fragment along.
    if (mCurState < Fragment.CREATED && fragment.mFromLayout) {
        moveToState(fragment, Fragment.CREATED, 0, 0, false);
    } else {
        moveToState(fragment);
    }

    if (fragment.mView == null) {
        throw new IllegalStateException("Fragment " + fname
                + " did not create a view.");
    }
    if (id != 0) {
        fragment.mView.setId(id);
    }
    if (fragment.mView.getTag() == null) {
        fragment.mView.setTag(tag);
    }
    return fragment.mView;
}

FragmentController#onCreateView

public View onCreateView(View parent, String name, Context context, AttributeSet attrs) {
    return mHost.mFragmentManager.onCreateView(parent, name, context, attrs);
}

FragmentManagerImpl#performPendingDeferredStart

public void performPendingDeferredStart(Fragment f) {
    if (f.mDeferStart) {
        if (mExecutingActions) {
            // Wait until we're done executing our pending transactions
            mHavePendingDeferredStart = true;
            return;
        }
        f.mDeferStart = false;
        moveToState(f, mCurState, 0, 0, false);
    }
}

FragmentManagerImpl#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.getAnimatingAway() != 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.setAnimatingAway(null);
            moveToState(f, f.getStateAfterAnimating(), 0, 0, true);
        }

        switch (f.mState) {
            case Fragment.INITIALIZING: //初始化状态

                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();
                dispatchOnFragmentPreAttached(f, mHost.getContext(), false);
                f.mCalled = false;

                //step 1: 执行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);
                }
                dispatchOnFragmentAttached(f, mHost.getContext(), false);

                if (!f.mRetaining) {
                    //step 2: 执行onCreate
                    f.performCreate(f.mSavedFragmentState);
                    dispatchOnFragmentCreated(f, f.mSavedFragmentState, false);
                } else {
                    f.restoreChildFragmentState(f.mSavedFragmentState);
                    f.mState = Fragment.CREATED;
                }
                f.mRetaining = false;

                //判断该fragment是否从布局中实例化
                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.
                    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);
                        dispatchOnFragmentViewCreated(f, f.mView, f.mSavedFragmentState, false);
                    } else {
                        f.mInnerView = null;
                    }
                }

            case Fragment.CREATED:  //created 状态
                if (newState > Fragment.CREATED) {

                    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;

                        //step 3:执行onCreateView
                        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) {
                                container.addView(f.mView);
                            }
                            if (f.mHidden) {
                                f.mView.setVisibility(View.GONE);
                            }

                            //step 4:执行onViewCreated
                            f.onViewCreated(f.mView, f.mSavedFragmentState);
                            dispatchOnFragmentViewCreated(f, f.mView, f.mSavedFragmentState,false);
                            // Only animate the view if it is visible. This is done after
                            // dispatchOnFragmentViewCreated in case visibility is changed
                            f.mIsNewlyAdded = (f.mView.getVisibility() == View.VISIBLE) && f.mContainer != null;
                        } else {
                            f.mInnerView = null;
                        }
                    }

                    //step 4: 执行onActivityCreated
                    f.performActivityCreated(f.mSavedFragmentState);
                    dispatchOnFragmentActivityCreated(f, f.mSavedFragmentState, false);
                    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();
                    dispatchOnFragmentStarted(f, false);
                }
            case Fragment.STARTED:
                if (newState > Fragment.STARTED) {
                    if (DEBUG) Log.v(TAG, "moveto RESUMED: " + f);
                    f.performResume();
                    dispatchOnFragmentResumed(f, false);
                    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();
                    dispatchOnFragmentPaused(f, false);
                }
            case Fragment.STARTED:
                if (newState < Fragment.STARTED) {
                    if (DEBUG) Log.v(TAG, "movefrom STARTED: " + f);
                    f.performStop();
                    dispatchOnFragmentStopped(f, false);
                }
            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();
                    dispatchOnFragmentViewDestroyed(f, false);
                    if (f.mView != null && f.mContainer != null) {
                        Animation anim = null;
                        if (mCurState > Fragment.INITIALIZING && !mDestroyed
                                && f.mView.getVisibility() == View.VISIBLE
                                && f.mPostponedAlpha >= 0) {
                            anim = loadAnimation(f, transit, false,
                                    transitionStyle);
                        }
                        f.mPostponedAlpha = 0;
                        if (anim != null) {
                            final Fragment fragment = f;
                            f.setAnimatingAway(f.mView);
                            f.setStateAfterAnimating(newState);
                            final View viewToAnimate = f.mView;
                            anim.setAnimationListener(new AnimateOnHWLayerIfNeededListener(
                                    viewToAnimate, anim) {
                                @Override
                                public void onAnimationEnd(Animation animation) {
                                    super.onAnimationEnd(animation);
                                    if (fragment.getAnimatingAway() != null) {
                                        fragment.setAnimatingAway(null);
                                        moveToState(fragment, fragment.getStateAfterAnimating(),
                                                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.getAnimatingAway() != 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.getAnimatingAway();
                            f.setAnimatingAway(null);
                            v.clearAnimation();
                        }
                    }
                    if (f.getAnimatingAway() != 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.setStateAfterAnimating(newState);
                        newState = Fragment.CREATED;
                    } else {
                        if (DEBUG) Log.v(TAG, "movefrom CREATED: " + f);
                        if (!f.mRetaining) {
                            f.performDestroy();
                            dispatchOnFragmentDestroyed(f, false);
                        } else {
                            f.mState = Fragment.INITIALIZING;
                        }

                        f.performDetach();
                        dispatchOnFragmentDetached(f, false);
                        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;
    }
}

上面方法通过不断改变当前的状态来完成生命周期的转变。其中,Fragment的onAttach和onCreate都是在Fragment.INITIALIZING中执行。onCreateView则要根据Fragment的布局是否从layout file中初始化。是则在Fragment.INITIALIZING中执行,否则是在Fragment.CREATED中执行。onActivityCreate是在Fragment.CREATED中执行。

以上便是Fragment的启动过程源码分析。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值