Fragment启动过程,从getFragmentManager开始

Posted yuminfeng728

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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)时,就是将对象中的参数初始化。而这些对象之间的关系,如下:

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

Fragment的学习使用

Fragment事物

Activity恢复时如何获取Fragment

Activity持有多个Fragment的跳转和回退实现方案

Android中Fragment怎样刷新UI

从现有片段启动其他片段时应用程序崩溃