一 简述
涉及到的类
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
操作时,需要保证Fragment
的mTag
和mContainerViewId
在不为空时(也就是这个Fragment
实例之前已经执行过add
操作),它们和新传入的tag
和containerViewId
必须是相同的,这是因为在FragmentManager
的mActive
列表中保存了所有被添加进去的Fragment
,而其提供的findFragmentById/Tag
正是通过这两个字段作为判断的标准,因此不允许同一个实例在列表当中重复出现两次。 replace
操作和add
类似,它增加了一个额外条件,就是containerViewId
不为空,因为replace
需要知道它是对哪个container
进行操作,后面我们会看到replace
其实是一个先remove
再add
的过程,因此`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);
}
}
}
这里的操作很多,我们需要明白以下几点:
mActive
和mAdded
的区别:mActive
表示执行过add
操作,并且其没有被移除(移除表示的是在不加入后退栈的情况下被removeFragment
),所有被动改变Fragment
状态的调用都是遍历这个列表;而mAdded
则表示执行过add
操作,并且没有执行detachFragment/removeFragment
,也就是说Fragment
是存在容器当中的,但是有可能是被隐藏的(hideFragment
)。attachFragment
必须保证其状态是mDetach
的,而该属性的默认值是false
,只有在执行过detach
方法后,才能执行,执行它会把f.mView
重新加入到container
中。detachFragment
会把f.mView
从container
中移除。removeFragment
和detachFragment
会强制改变Fragment
的状态,这是因为它们需要改变Fragment
在布局中的位置,而这通过被动地接收FragmentManager
状态(即所在Activity
的状态)是无法实现的。在removeFragment
时,会根据是否加入后退栈来区分,如果假如了后退栈,因为有可能之后会回退,而回退时遍历的是mActive
列表,如果把它的状态置为Fragment.INITIALZING
,那么在moveToState
方法中就会走到最后一步,把它从mActive
列表中移除,就找不到了也就无法恢复,因此这种情况下Fragment
最终的状态的和detachFragment
是相同的。- 在加入后退栈时,
detachFragment
时,会把mDetach
置为true
,这种情况下之后可以执行attachFragment
操作但不能执行addFragment
操作;removeFragment
之后可以执行addFragment
操作但不能执行attachFragment
操作。 showFragment
和hideFragment
并不会主动改变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的生命周期如下: