源码理解Fragment机制

一  简述

涉及到的类

frameworks/base/core/java/android/app/Activity.java

  •  Activity类, AMS控制的生命周期都是回调给Activity

frameworks/base/core/java/android/app/Fragment.java

  •  Fragment,被实现对象,被回调生命周期对象

frameworks/base/core/java/android/app/FragmentController.java 

  • FragmentController 其实是一个代理类,代理FragmentManager那些方法

frameworks/base/core/java/android/app/FragmentHostCallback.java

  •   FragmentHostCallback 这是一个抽象类,需要主体实现,里面实现一些Fragment机制中所不能实现的功能,比如请求权限,这些都需要主体来实现

frameworks/base/core/java/android/app/FragmentManager.java

  • Fragment的管理类,被FragmentHostCallback持有,负责控制Fragment的状态,真正做操作的类

二  Fragment体系类介绍

我们从Activity下手, 从getFragmentManager来看,我们是去从FragmentController中获取的FragmentManager。

public class Activity extends... {

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

    /**
     * Return the FragmentManager for interacting with fragments associated
     * with this activity.
     */
    public FragmentManager getFragmentManager() {
        return mFragments.getFragmentManager();
    }

    // 在这里实现FragmentHostCallback所无法实现的那些功能,列如activituy跳转的数据结果等
    class HostCallbacks extends FragmentHostCallback<Activity> {
      ...
    }
}

从FragmentController的源码可以看到,构造方法的参数为: FragmentHostCallback且,这是唯一的变量。
然后其他方法都是代理, 都调用的是mHost.mFragmentManager中的同名方法。
代码如下:

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;
    }

    // 调用mHost.mFragmentManager的同名方法
    public void dispatchResume() {
        mHost.mFragmentManager.dispatchResume();
    }

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

     ....
}

我们在前面看Activity初始化FragmentControl的时候,会传FragmentHostCallback类,

那么mHost.mFragmentManager是什么呢,其是FragmentManagerImpl类,这个是FragmentManger的一个内部类,也继承于FragmentManger, 并且实现了LayoutInflaterFactory接口。是个做实事的家伙。

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(null /*activity*/, context, handler, windowAnimations);
    }
    ...
  }

FragmentManagerImpl类是最核心的类,Fragment由其管理,各种安全检查也由其做。代码如下

final class FragmentManagerImpl extends FragmentManager implements LayoutInflater.Factory2 {
    static final String TAG = "FragmentManager";

    ArrayList<OpGenerator> mPendingActions;
    boolean mExecutingActions;

    int mNextFragmentIndex = 0;
    SparseArray<Fragment> mActive;
    final ArrayList<Fragment> mAdded = new ArrayList<>();
    ArrayList<BackStackRecord> mBackStack;
    ArrayList<Fragment> mCreatedMenus;

    // Must be accessed while locked.
    ArrayList<BackStackRecord> mBackStackIndices;
    ArrayList<Integer> mAvailBackStackIndices;

    ArrayList<OnBackStackChangedListener> mBackStackChangeListeners;
    final CopyOnWriteArrayList<Pair<FragmentLifecycleCallbacks, Boolean>>
            mLifecycleCallbacks = new CopyOnWriteArrayList<>();

    int mCurState = Fragment.INITIALIZING;
    FragmentHostCallback<?> mHost;
    FragmentContainer mContainer;
    Fragment mParent;
    Fragment mPrimaryNav;

    boolean mNeedMenuInvalidate;
    boolean mStateSaved;
    boolean mDestroyed;
    String mNoTransactionsBecause;
    boolean mHavePendingDeferredStart;

    // Temporary vars for removing redundant operations in BackStackRecords:
    ArrayList<BackStackRecord> mTmpRecords;
    ArrayList<Boolean> mTmpIsPop;
    ArrayList<Fragment> mTmpAddedFragments;

    // Temporary vars for state save and restore.
    Bundle mStateBundle = null;
    SparseArray<Parcelable> mStateArray = null;

    // Postponed transactions.
    ArrayList<StartEnterTransitionListener> mPostponedTransactions;

    // Prior to O, we allowed executing transactions during fragment manager state changes.
    // This is dangerous, but we want to keep from breaking old applications.
    boolean mAllowOldReentrantBehavior;

    // Saved FragmentManagerNonConfig during saveAllState() and cleared in noteStateNotSaved()
    FragmentManagerNonConfig mSavedNonConfig;

我们可以看到,里面有各种状态位保存,回退栈等,都在这个类里面记录。

到这里我们应该知道Fragment体系的几个类是干嘛的了。接下从一个方法来看看Fragment的事务如何处理。

三  Fragment事务

我们一般使用Fragment是按照下面这样使用的,开启一个事务,最后commit

FragmentTransaction transaction = getFragmentManager().beginTransaction();
  transaction.replace(R.id.main_fragment_container, homeFragment);
   transaction.commit();

我们来看下beginTransaction方法的实现

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

可以见到,其返回了一个BackStackRecord类,那么这个类是继承于FragmentTransaction的

它的实现是BackStackRecord,并且在每次 beginTransaction时都是返回一个新的事务对象,包括之后进行的后退操作都是通过这个事务对象来管理的,这个对象中保存了创建它的FragmentManagerImpl实例。 BackStackRecord其实是BackStackState的一个内部类,我们平时就是通过它来进行add、remove、replace、attach、detach、hide、show等操作的

/**
 * @hide Entry of an operation on the fragment back stack.
 */
final class BackStackRecord extends FragmentTransaction implements
        FragmentManager.BackStackEntry, FragmentManagerImpl.OpGenerator {
    static final String TAG = FragmentManagerImpl.TAG;

    final FragmentManagerImpl mManager;

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

    // 链表节点
    static final class Op {
        int cmd;      // 表明动作
        Fragment fragment;  //被操作的Fragment
        int enterAnim;  // 进入动画
        int exitAnim;   // 退出动画
        int popEnterAnim;  // 弹入动画
        int popExitAnim;   // 弹出动画

        Op() {
        }

        Op(int cmd, Fragment fragment) {
            this.cmd = cmd;
            this.fragment = fragment;
        }
    }

    ArrayList<Op> mOps = new ArrayList<>();  
    int mEnterAnim;
    int mExitAnim;
    int mPopEnterAnim;
    int mPopExitAnim;
    int mTransition;
    int mTransitionStyle;
    boolean mAddToBackStack;
    boolean mAllowAddToBackStack = true;
    String mName;
    boolean mCommitted;
    int mIndex = -1;
    boolean mReorderingAllowed;

    ArrayList<Runnable> mCommitRunnables;

    int mBreadCrumbTitleRes;
    CharSequence mBreadCrumbTitleText;
    int mBreadCrumbShortTitleRes;
    CharSequence mBreadCrumbShortTitleText;

    ArrayList<String> mSharedElementSourceNames;
    ArrayList<String> mSharedElementTargetNames;
final class BackStackRecord extends FragmentTransation implements FragmentManager.BackStackEntry, Runnable {

    public FragmentTransation add(Fragment fragment, String tag) {
        doAddOp(0, fragment, tag, OP_ADD);
        return this;
    }

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

    public FragmentTransation add(int containerViewId, Fragment fragment, String tag) {
        doAddOp(containerViewId, fragment, tag, OP_ADD);
    }

    public FragmentTransation replace(int containerViewId, Fragment fragment) {
        return replace(containerViewId, fragment, null);
    }

    public FragmentTransation replace(int containerViewId, Fragment fragment, String tag) {
        if (containerViewId == 0) {
            //replace操作必须要指定containerViewId.
        }
        doAddOp(containerViewId, fragment, tag, OP_REPLACE);
    }

    public FragmentTransaction remove(Fragment fragment) {
        Op op = new Op();
        op.cmd = OP_REMOVE;
        op.fragment = fragment;
        addOp(op);
    }

    public FragmentTransaction hide(Fragment fragment) {
        Op op = new Op();
        op.cmd = OP_HIDE;
        op.fragment = fragment;
        addOp(op);
    }

    public FragmentTransaction show(Fragment fragment) {
        Op op = new Op();
        op.cmd = OP_SHOW;
        op.fragment = fragment;
        addOp(op);
    }

    public FragmentTransaction attach(Fragment fragment) {
        Op op = new Op();
        op.cmd = OP_ATTACH;
        op.fragment = fragment;
        addOp(op);
    }

    public FragmentTransaction detach(Fragment fragment) {
        Op op = new Op();
        op.cmd = OP_DETACH;
        op.fragment = fragment;
        addOp(op);
    }

    //新建一个操作,并给操作赋值。
    private void doAddOp(int containerViewId, Fragment fragment, String tag, int opcmd) {
        fragment.mFragmentManager = mManager;
        if (tag != null) {
            if (fragment.mTag != null && !tag.equals(fragment.mTag)) {
                //如果这个 fragment 之前已经有了tag,那么是不允许改变它的。
            }
            fragment.mTag = tag;
        }
        if (containerViewId != 0) {
            if (fragment.mFragmentId != 0 && fragment.mFragmentId != containerViewId) {
                //如果这个fragment已经有了mFragmentId,那么不允许改变它。
            }
            fragment.mContainerId = fragment.mFragmentId = containerViewId;
        }
        Op op = new Op();
        op.cmd = opcmd;
        op.fragment = fragment;
        addOp(op);
    }

    //把操作添加到链表之中。
    void addOp() {
        if (mHead == null) {
            mHead = mTail = op;
        } else {
            op.prev = mTail;
            mTail.next = op;
            mTail = op;
        }
        mNumOp++;
    }
}

看完上面这段代码,我们可以得到下面这些信息:

  • 我们调用这些操作之后仅仅是把这个操作添加到了BackStackRecord当中的一个链表。
  • 在进行attach、detach、hide、show、remove这五个操作时是不需要传入containerViewId的,因为在执行这些操作之前这个Fragment必然已经经过了add操作,它的containerId是确定的。
  • 在执行add操作时,需要保证FragmentmTagmContainerViewId在不为空时(也就是这个 Fragment实例之前已经执行过add操作),它们和新传入的tagcontainerViewId必须是相同的,这是因为在FragmentManagermActive列表中保存了所有被添加进去的Fragment,而其提供的 findFragmentById/Tag正是通过这两个字段作为判断的标准,因此不允许同一个实例在列表当中重复出现两次。
  • replace操作和add类似,它增加了一个额外条件,就是containerViewId不为空,因为replace需要知道它是对哪个container进行操作,后面我们会看到replace其实是一个先removeadd的过程,因此`add 的那些判断条件同样适用。

我们从其add方法来看

public FragmentTransaction add(Fragment fragment, String tag) {
    doAddOp(0, fragment, tag, OP_ADD);
    return this;
}

private void doAddOp(int containerViewId, Fragment fragment, String tag, int opcmd) {
    if (mManager.getTargetSdk() > Build.VERSION_CODES.N_MR1) {
        final Class fragmentClass = fragment.getClass();
        final int modifiers = fragmentClass.getModifiers();
        if ((fragmentClass.isAnonymousClass() || !Modifier.isPublic(modifiers)
                || (fragmentClass.isMemberClass() && !Modifier.isStatic(modifiers)))) {
            throw new IllegalStateException("Fragment " + fragmentClass.getCanonicalName()
                    + " must be a public static class to be  properly recreated from"
                    + " instance state.");
        }
    }
    fragment.mFragmentManager = mManager;

    if (tag != null) {
        ....
        fragment.mTag = tag;
    }

    if (containerViewId != 0) {
        ...
        fragment.mContainerId = fragment.mFragmentId = containerViewId;
    }

    addOp(new Op(opcmd, fragment));
}

void addOp(Op op) {
    mOps.add(op);
    op.enterAnim = mEnterAnim;
    op.exitAnim = mExitAnim;
    op.popEnterAnim = mPopEnterAnim;
    op.popExitAnim = mPopExitAnim;
}

可以看到,其将整个操作封装成了一个Op并将其添加到mOps列表里面去。这个列表是我们在上面定义的,一个链表。

这个流程到这其实就结束了,接下来我们会调用commit()方法。
commit里面调用FragmentManager的enqueueAction方法

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

int commitInternal(boolean allowStateLoss) {
    if (mCommitted) {
        throw new IllegalStateException("commit already called");
    }
    if (FragmentManagerImpl.DEBUG) {
        Log.v(TAG, "Commit: " + this);
        LogWriter logw = new LogWriter(Log.VERBOSE, TAG);
        PrintWriter pw = new FastPrintWriter(logw, false, 1024);
        dump("  ", null, pw, null);
        pw.flush();
    }
    mCommitted = true;
    if (mAddToBackStack) {
        mIndex = mManager.allocBackStackIndex(this);
    } else {
        mIndex = -1;
    }
    mManager.enqueueAction(this, allowStateLoss);  //调用FragmentManager的enqueueAction方法
    return mIndex;
}

FragmentManager中将操作添加进pendingAction中

/**
 * Adds an action to the queue of pending actions.
 *
 * @param action the action to add
 * @param allowStateLoss whether to allow loss of state information
 * @throws IllegalStateException if the activity has been destroyed
 */
public void enqueueAction(OpGenerator action, boolean allowStateLoss) {
    if (!allowStateLoss) {
        checkStateLoss();  // 这边会检查状态,若activity已经走了onSaveInstanceStatus,这边会抛出异常
    }
    synchronized (this) {
        if (mDestroyed || mHost == null) {
            if (allowStateLoss) {
                // This FragmentManager isn't attached, so drop the entire transaction.
                return;
            }
            throw new IllegalStateException("Activity has been destroyed");
        }
        if (mPendingActions == null) {
            mPendingActions = new ArrayList<>();
        }
         // 将commit处理操作放置到mPendingActions列表中
        mPendingActions.add(action);
        scheduleCommit();
    }
}

接下来开启执行的runnable,进行调度动作

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

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中的execPendingActions()方法

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

    boolean didSomething = false;
    // 进入死循环, generateOpsForPendingActions会判断当前是否还有任务
    while (generateOpsForPendingActions(mTmpRecords, mTmpIsPop)) {
        mExecutingActions = true;
        try {
            // 去掉多余任务,并执行任务
            // 执行任务的时候,会去挨个调用BackStackRecord中的expandOps方法。里面会执行之前的Ops
            removeRedundantOperationsAndExecute(mTmpRecords, mTmpIsPop);
        } finally {
            // 清理多余任务
            cleanupExec();
        }
        didSomething = true;
    }

    doPendingDeferredStart();
    burpActive();

    return didSomething;
}

我们看一下 removeRedundantOperationsAndExecute里面调用BackStackRecord中的expandOps方法的逻辑,在这里就负责取出各个事务进行操作 record.executeOps()。

    private void executeOpsTogether(ArrayList<BackStackRecord> records,
            ArrayList<Boolean> isRecordPop, int startIndex, int endIndex) {
        final boolean allowReordering = records.get(startIndex).mReorderingAllowed;
        boolean addToBackStack = false;
        if (mTmpAddedFragments == null) {
            mTmpAddedFragments = new ArrayList<>();
        } else {
            mTmpAddedFragments.clear();
        }
        mTmpAddedFragments.addAll(mAdded);
        Fragment oldPrimaryNav = getPrimaryNavigationFragment();
        for (int recordNum = startIndex; recordNum < endIndex; recordNum++) {
            final BackStackRecord record = records.get(recordNum);
            final boolean isPop = isRecordPop.get(recordNum);
            if (!isPop) {
                oldPrimaryNav = record.expandOps(mTmpAddedFragments, oldPrimaryNav);
            } else {
                record.trackAddedFragmentsInPop(mTmpAddedFragments);
            }
            addToBackStack = addToBackStack || record.mAddToBackStack;
        }
        mTmpAddedFragments.clear();

        if (!allowReordering) {
            FragmentTransition.startTransitions(this, records, isRecordPop, startIndex, endIndex,
                    false);
        }
        executeOps(records, isRecordPop, startIndex, endIndex);

        int postponeIndex = endIndex;
        if (allowReordering) {
            ArraySet<Fragment> addedFragments = new ArraySet<>();
            addAddedFragments(addedFragments);
            postponeIndex = postponePostponableTransactions(records, isRecordPop,
                    startIndex, endIndex, addedFragments);
            makeRemovedFragmentsInvisible(addedFragments);
        }

        if (postponeIndex != startIndex && allowReordering) {
            // need to run something now
            FragmentTransition.startTransitions(this, records, isRecordPop, startIndex,
                    postponeIndex, true);
            moveToState(mCurState, true);
        }

        for (int recordNum = startIndex; recordNum < endIndex; recordNum++) {
            final BackStackRecord record = records.get(recordNum);
            final boolean isPop = isRecordPop.get(recordNum);
            if (isPop && record.mIndex >= 0) {
                freeBackStackIndex(record.mIndex);
                record.mIndex = -1;
            }
            record.runOnCommitRunnables();
        }

        if (addToBackStack) {
            reportBackStackChanged();
        }
    }
Fragment expandOps(ArrayList<Fragment> added, Fragment oldPrimaryNav) {
     //遍历链表挨个取出动作进行执行
     for (int opNum = 0; opNum < mOps.size(); opNum++) {
         final Op op = mOps.get(opNum);
         switch (op.cmd) {
             case OP_ADD:
             case OP_ATTACH:
                 added.add(op.fragment);
                 break;
             case OP_REMOVE:
             case OP_DETACH: {
                 added.remove(op.fragment);
                 if (op.fragment == oldPrimaryNav) {
                     mOps.add(opNum, new Op(OP_UNSET_PRIMARY_NAV, op.fragment));
                     opNum++;
                     oldPrimaryNav = null;
                 }
             }
             break;
             case OP_REPLACE: {
                 final Fragment f = op.fragment;
                 final int containerId = f.mContainerId;
                 boolean alreadyAdded = false;
                 for (int i = added.size() - 1; i >= 0; i--) {
                     final Fragment old = added.get(i);
                     if (old.mContainerId == containerId) {
                         if (old == f) {
                             alreadyAdded = true;
                         } else {
                             // This is duplicated from above since we only make
                             // a single pass for expanding ops. Unset any outgoing primary nav.
                             if (old == oldPrimaryNav) {
                                 mOps.add(opNum, new Op(OP_UNSET_PRIMARY_NAV, old));
                                 opNum++;
                                 oldPrimaryNav = null;
                             }
                             final Op removeOp = new Op(OP_REMOVE, old);
                             removeOp.enterAnim = op.enterAnim;
                             removeOp.popEnterAnim = op.popEnterAnim;
                             removeOp.exitAnim = op.exitAnim;
                             removeOp.popExitAnim = op.popExitAnim;
                             mOps.add(opNum, removeOp);
                             added.remove(old);
                             opNum++;
                         }
                     }
                 }
                 if (alreadyAdded) {
                     mOps.remove(opNum);
                     opNum--;
                 } else {
                     op.cmd = OP_ADD;
                     added.add(f);
                 }
             }
             break;
             case OP_SET_PRIMARY_NAV: {
                 // It's ok if this is null, that means we will restore to no active
                 // primary navigation fragment on a pop.
                 mOps.add(opNum, new Op(OP_UNSET_PRIMARY_NAV, oldPrimaryNav));
                 opNum++;
                 // Will be set by the OP_SET_PRIMARY_NAV we inserted before when run
                 oldPrimaryNav = op.fragment;
             }
             break;
         }
     }
     return oldPrimaryNav;
 }
    private static void executeOps(ArrayList<BackStackRecord> records,
            ArrayList<Boolean> isRecordPop, int startIndex, int endIndex) {
        for (int i = startIndex; i < endIndex; i++) {
            final BackStackRecord record = records.get(i);
            final boolean isPop = isRecordPop.get(i);
            if (isPop) {
                record.bumpBackStackNesting(-1);
                // Only execute the add operations at the end of
                // all transactions.
                boolean moveToState = i == (endIndex - 1);
                record.executePopOps(moveToState);
            } else {
                record.bumpBackStackNesting(1);
                record.executeOps();
            }
        }
    }
    /**
     * Reverses the execution of the operations within this transaction. The Fragment states will
     * only be modified if optimizations are not allowed.
     *
     * @param moveToState {@code true} if added fragments should be moved to their final state
     *                    in unoptimized transactions
     */
    void executePopOps(boolean moveToState) {
        for (int opNum = mOps.size() - 1; opNum >= 0; opNum--) {
            final Op op = mOps.get(opNum);
            Fragment f = op.fragment;
            if (f != null) {
                f.setNextTransition(FragmentManagerImpl.reverseTransit(mTransition),
                        mTransitionStyle);
            }
            switch (op.cmd) {
                case OP_ADD:
                    f.setNextAnim(op.popExitAnim);
                    mManager.removeFragment(f);
                    break;
                case OP_REMOVE:
                    f.setNextAnim(op.popEnterAnim);
                    mManager.addFragment(f, false);
                    break;
                case OP_HIDE:
                    f.setNextAnim(op.popEnterAnim);
                    mManager.showFragment(f);
                    break;
                case OP_SHOW:
                    f.setNextAnim(op.popExitAnim);
                    mManager.hideFragment(f);
                    break;
                case OP_DETACH:
                    f.setNextAnim(op.popEnterAnim);
                    mManager.attachFragment(f);
                    break;
                case OP_ATTACH:
                    f.setNextAnim(op.popExitAnim);
                    mManager.detachFragment(f);
                    break;
                case OP_SET_PRIMARY_NAV:
                    mManager.setPrimaryNavigationFragment(null);
                    break;
                case OP_UNSET_PRIMARY_NAV:
                    mManager.setPrimaryNavigationFragment(f);
                    break;
                default:
                    throw new IllegalArgumentException("Unknown cmd: " + op.cmd);
            }
            if (!mReorderingAllowed && op.cmd != OP_REMOVE && f != null) {
                mManager.moveFragmentToExpectedState(f);
            }
        }
        if (!mReorderingAllowed && moveToState) {
            mManager.moveToState(mManager.mCurState, true);
        }
    }

 我们来看一下FragmentManagerImpl对应的addFragment等操作:

public void addFragment(Fragment fragment, boolean moveToStateNow) {
   makeActive(fragment); //加入到mActive列表中。
   if (!fragment.mDetached) {
       if (mAdd.contains(fragment)) {
           //已经在mAdded列表,抛出异常。
       }
       mAdded.add(fragment);
       fragment.mAdded = true;
       fragment.mRemoving = false;
       if (moveToStateNow) {
           moveToState(fragment);
       }
   }
}

public void removeFragment(Fragment fragment, int transition, int transitionStyle) {
    final boolean inactive = !fragment.isInBackStack();
    if (!fragment.mDetach || inactive) {
        if (mAdded != null) {
            mAdded.remove(fragment); //从mAdded列表中移除。
        }
        fragment.mAdded = false;
        fragment.mRemoving = true;
        //这里会根据是否加入后退栈来判断新的状态,最后会影响到Fragment生命周期的调用,如果是没有加入后退栈的,那么会多调用onDestroy、onDetach方法。
        moveToState(fragment, inactive ? Fragment.INITIALZING : Fragment.CREATED, transition, transitionStyle, false); 
    }
}

public void hideFragment(Fragment fragment, int transition, int transitionStyle) {
    if (!fragment.mHidden) {
       fragment.mHidden = true;
       if (fragment.mView != null) {
          fragment.mView.setVisibility(View.GONE);
       }
    }
    fragment.onHiddenChanged(true);
}

public void showFragment(Fragment fragment, int transition, int transitionStyle) {
    if (fragment.mHidden) {
        fragment.mHidden = false;
        if (fragment.mView != null) {
             fragment.mView.setVisibility(View.VISIBLE);
        }
        fragment.onHiddenChanged(false);
    }
}

public void detachFragment(Fragment fragment, int transition, int transitionStyle) {
    if (!fragment.mDetached) {
        fragment.mDetached = true;
        if (fragment.mAdded) {
             if (mAdded != null) {
                 mAdded.remove(fragment);
             }
             fragment.mAdded = false;
             moveToState(fragment, Fragment.CREATED, transition, transitionStyle, false);
        }
    }
}

public void attachFragment(Fragment fragment, int transition, int transitionStyle) {
    if (fragment.mDetached) {
         if (!fragment.mAdded) {
              if (mAdded.contains(fragment)) {
                  //mAdded列表中已经有,抛出异常,
              }
              mAdded.add(fragment);
              fragment.mAdded = true;
              moveToState(fragment, mCurState, transition, transitionStyle, false);
         }
    }

}

这里的操作很多,我们需要明白以下几点:

  • mActivemAdded的区别:mActive表示执行过add操作,并且其没有被移除(移除表示的是在不加入后退栈的情况下被removeFragment),所有被动改变Fragment状态的调用都是遍历这个列表;而 mAdded则表示执行过add操作,并且没有执行detachFragment/removeFragment,也就是说Fragment 是存在容器当中的,但是有可能是被隐藏的(hideFragment)。
  • attachFragment 必须保证其状态是 mDetach 的,而该属性的默认值是 false,只有在执行过 detach 方法后,才能执行,执行它会把 f.mView 重新加入到 container 中。
  • detachFragment 会把 f.mViewcontainer 中移除。
  • removeFragmentdetachFragment 会强制改变 Fragment 的状态,这是因为它们需要改变 Fragment 在布局中的位置,而这通过被动地接收 FragmentManager 状态(即所在Activity的状态)是无法实现的。在 removeFragment 时,会根据是否加入后退栈来区分,如果假如了后退栈,因为有可能之后会回退,而回退时遍历的是 mActive 列表,如果把它的状态置为Fragment.INITIALZING,那么在 moveToState方法中就会走到最后一步,把它从mActive列表中移除,就找不到了也就无法恢复,因此这种情况下Fragment最终的状态的和detachFragment是相同的。
  • 在加入后退栈时,detachFragment 时,会把 mDetach置为true,这种情况下之后可以执行 attachFragment操作但不能执行 addFragment操作;removeFragment 之后可以执行 addFragment操作但不能执行 attachFragment操作。
  • showFragmenthideFragment 并不会主动改变 Fragment 的状态,它仅仅是回调 onHiddenChanged方法,其状态还是跟着 FragmentManager 来走。
mManager.moveToState(mManager.mCurState, mTransition, mTransitionStyle, true); 

到 moveToState方法中,我们看到了许多熟悉的面孔,就是我们平时最常谈到的 Fragment 的生命周期,通过这段代码我们就可以对它的生命周期有更加直观的理解。

四  Fragment的生命周期回调

对于Fragment的生命周期,很多人都理解不懂,毕竟生命周期过多,从源码看,应该会好很多。我们看下Activity是如何回调Fragment的生命周期的。

Activity源码中:

protected void onCreate(@Nullable Bundle savedInstanceState) {
 ...
   //调用FragmnentController的 dispatchCreate方法
    mFragments.dispatchCreate();
}

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

FragmentManager中

public void dispatchCreate() {
    mStateSaved = false;
    dispatchMoveToState(Fragment.CREATED);
}

private void dispatchMoveToState(int state) {
    if (mAllowOldReentrantBehavior) {
        moveToState(state, false);
    } else {
        try {
            mExecutingActions = true;
            moveToState(state, false);
        } finally {
            mExecutingActions = false;
        }
    }
    execPendingActions();
}

最后会调到:
这个方法特别长,

static final int INVALID_STATE = -1;   // Invalid state used as a null value.
static final int INITIALIZING = 0;     // Not yet created.
static final int CREATED = 1;          // Created.
static final int ACTIVITY_CREATED = 2; // The activity has finished its creation.
static final int STOPPED = 3;          // Fully created, not started.
static final int STARTED = 4;          // Created and started, not resumed.
static final int RESUMED = 5;          // Created started and resumed.

void moveToState(Fragment f, int newState, int transit, int transitionStyle,
        boolean keepActive) {
    switch (f.mState) {
         case Fragment.INITIALIZING:   //里面会回调onAttach
              ...
              f.onAttach(mHost.getContext());
              break;
         case Fragment.CREATED:
              f.mView = f.performCreateView(f.performGetLayoutInflater(  // 回调onCreateView
                               f.mSavedFragmentState), container, f.mSavedFragmentState);
              f.onViewCreated(f.mView, f.mSavedFragmentState);      // 回调onViewCreated
              f.performActivityCreated(f.mSavedFragmentState);      // 回调 onActivityCreated(savedInstanceState);
               dispatchOnFragmentActivityCreated(f, f.mSavedFragmentState, false);  
              if (f.mView != null) {
                  f.restoreViewState(f.mSavedFragmentState);     // 回调 onViewStateRestored(savedInstanceState);
              }
              case Fragment.ACTIVITY_CREATED:
                  if (newState > Fragment.ACTIVITY_CREATED) {
                      f.mState = Fragment.STOPPED;
                  }
                  // fall through
              case Fragment.STOPPED:
                  if (newState > Fragment.STOPPED) {
                      if (DEBUG) Log.v(TAG, "moveto STARTED: " + f);
                      f.performStart();                          // 回调 onStart
                      dispatchOnFragmentStarted(f, false);
                  }
                  // fall through
              case Fragment.STARTED:
                  if (newState > Fragment.STARTED) {
                      if (DEBUG) Log.v(TAG, "moveto RESUMED: " + f);
                      f.performResume();                        // 回调 onResume
                      dispatchOnFragmentResumed(f, false);
                      // Get rid of this in case we saved it and never needed it.
                      f.mSavedFragmentState = null;
                      f.mSavedViewState = null;
                  }
              ....

}

其他的生命周期也是类似的,大体都一样Activity源码中

final void performPause() {
    mDoReportFullyDrawn = false;
    mFragments.dispatchPause();     // 通知Fragment onPause
    mCalled = false;
    onPause();                      //Activity自身onPause
    mResumed = false;
    if (!mCalled && getApplicationInfo().targetSdkVersion
            >= android.os.Build.VERSION_CODES.GINGERBREAD) {
        throw new SuperNotCalledException(
                "Activity " + mComponent.toShortString() +
                " did not call through to super.onPause()");
    }
    mResumed = false;
}


final void performResume() {
    performRestart();

    mFragments.execPendingActions();

    mLastNonConfigurationInstances = null;

    mCalled = false;
    // mResumed is set by the instrumentation
    mInstrumentation.callActivityOnResume(this);      // 调用Activity的onResume

    // Now really resume, and install the current status bar and menu.
    mCalled = false;

    mFragments.dispatchResume();     // 调用Fragment的onResume
    mFragments.execPendingActions();

    onPostResume();
    if (!mCalled) {
        throw new SuperNotCalledException(
            "Activity " + mComponent.toShortString() +
            " did not call through to super.onPostResume()");
    }
}

通过阅读这些源码,我们可以总结出Fragment的生命周期如下:

  • 9
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值