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的啓動過程源碼分析。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章