1.概述
Fragment已经成为Android开发中应用比较广泛的方案了,几乎每一个APP都离不开它的影子。为了更深入的理解其中原理,我们从Fragment中源码开始分析。
Fragment生命周期 如果我们需要在Activity添加一个Fragment,代码如下:
public class MainActivity extends Activity{
ContentFragment mContentFragment;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mContentFragment = ContentFragment.newInstance(null);
getFragmentManager()
.beginTransaction()
.replace(R.id.container,mContentFragment)
.commit();
}
}
先大致介绍下即将遇到的几个类。
- ActivityThread : Android 入口类
- Instrumentation : ActivityThread 的工具类
- HostCallbacks : Activity 的内部类,继承自 FragmentHostCallback
- FragmentHostCallback : 持有 Handler、FragmentManagerImpl 等等对象的引用,别的对象可以通过持有它的引用间接控制 FragmentManagerImpl 等等对象
- FragmentController : Activity 通过控制它间接向 FragmentManagerImpl 发出命令
- FragmentManagerImpl : 顾名思义,它继承自 FragmentManager,用来对 Fragment 进行管理,在 FragmentHostCallback 中被初始化
- BackStackRecord : 继承自 FragmentTransation 并实现了 Runnable,每次调用 FragmentManager 对象的 beginTransaction() 方法都会产生一个 BackStackRecord 对象,可以将其理解为对 Fragment 的一系列操作(即事务)
- Op : 每次对 Fragment 的操作都会产生一个 Op 对象,其表示双向链表的一个结点
UML图:
2.Fragment事务的执行过程
从getFragmentManager()方法开始:
Activity.java
final FragmentController mFragments = FragmentController.createController(new HostCallbacks());
.....
@Deprecated
public FragmentManager getFragmentManager() {
return mFragments.getFragmentManager();
}
这里的mFragments是FragmentController类实例,在Activity类内部申明时已经初始化,所以在ActivityThread中创建Activity实例的时候mFragments对象已被创建。
再来看下FragmentController类中对应的方法;
FragmentController.java
private final FragmentHostCallback<?> mHost;
public static final FragmentController createController(FragmentHostCallback<?> callbacks) {
return new FragmentController(callbacks)
}
private FragmentController(FragmentHostCallback<?> callbacks) {
mHost = callbacks;
}
public FragmentManager getFragmentManager() {
return mHost.getFragmentManagerImpl();
}
FragmentController是把一个callback包装了起来,真正完成任务的是FragmentHostCallback。
final FragmentManagerImpl mFragmentManager = new FragmentManagerImpl();
FragmentManagerImpl getFragmentManagerImpl() {
return mFragmentManagerImpl;
}
所以最终得到的是FragmentMangerImpl对象。
之后继续Fragment的业务我们需要通过FragmentManger的beginTransaction方法得到一个事务,FragmentImpl中的具体实现为:
final class FragmentManagerImpl extends FragmentManager implements LayoutInflater.Factory2 {
public FragmentTransaction beginTransation() {
return new BackStackRecord(this);
}
}
FragmentTransation也是一个接口,他的具体实现为BackStackRecord,并且每次beginTrasaction时返回的都是一个新的事务对象,包括之后进行的后退操作都是通过这个事务对象看来管理的,BackStackRecord对象中保存了创建他的FragmentManagerImpl实例。
BackStackRecord.java
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) {
}
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.mTag = tag;
}
if (containerViewId != 0) {
if (fragment.mFragmentId != 0 && fragment.mFragmentId != containerViewId) {
}
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++;
}
}
可以看到我们调用add、remove、hide、replace等方法的时候,这些操作都会被实例化成Op对象,然后加入到一个集合中。这些操作真正被执行是在commit方法中。
public int commit() {
return commitInternal(false);
}
int commitInternal(boolean allowStateLoss) {
if (mCommitted) {
}
mCommited = true;
if (mAddToBackState) {
mIndex = mManager.allocBackStackIndex(this);
} else {
mIndex = -1;
}
mManager.enqueueAction(this, allowStateLoss);
}
最终调用了FragmentManger的enqueueAction方法:
FragmentManager.java
public void enqueueAction(OpGenerator action, boolean allowStateLoss) {
if (!allowStateLoss) {
checkStateLoss();
}
synchronized (this) {
if (mDestroyed || mHost == null) {
if (allowStateLoss) {
return;
}
throw new IllegalStateException("Activity has been destroyed");
}
if (mPendingActions == null) {
mPendingActions = new ArrayList<>();
}
mPendingActions.add(action);
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();
}
};
public boolean execPendingActions() {
ensureExecReady(true);
boolean didSomething = false;
while (generateOpsForPendingActions(mTmpRecords, mTmpIsPop)) {
mExecutingActions = true;
try {
removeRedundantOperationsAndExecute(mTmpRecords, mTmpIsPop);
} finally {
cleanupExec();
}
didSomething = true;
}
doPendingDeferredStart();
burpActive();
return didSomething;
}
- 在调用commit之后,把BackStackRecord加入到FragmentManagerImpl的mPendingActions中,而且通过查看FragmentManager的源码也可以发现,所有对mPendingActions的添加操作只有这一个地方调用,
- 当其大小为1时,会通过主线程的Handler post一个Runnable mExecCommit出去,当这个Runnable执行时调用execPendingActions()方法。
- execPendingActions它会拿出这个mPendingActions当中的所有Runnable执行(如果它是 BackStackRecord调用过来的,那么就是调用BackStackRecord的run方法),并把这个列表清空。在每个BackStackRecord的run方法执行时,它是通过遍历BackStackRecord链表当中每个节点的cmd来判断我们之前通过FragmentTransation加入期望执行的那些操作的。
- 可以看出execPendingActions这个方法很关键,因为它决定了我们添加的操作什么时候会被执行,我们看下还有那些地方调用到了它,为什么要分析这个呢,因为我们在项目当中发现很多来自于Fragment的异常都是由我们后面谈论的moveToState方法抛出的,而moveToState执行的原因是execPendingActions被调用了,因此了解它被调用的时机是我们追踪问题的关键,关于调用的时机,我们都总结在下面的注释当中了:
<!-- Activity.java -->
final void performStart() {
mFragments.execPendingActions();
mInstrumentation.callActivityOnStart(this);
}
final void performResume() {
performRestart();
mFragments.execPendingActions();
....
mInstrumentation.callActivityOnResume(this);
....
mFragments.dispatchResume();
mFragments.execPendingActions();
}
<!-- FragmentManager.java -->
public void dispatchDestroy() {
execPendingActions();
}
public boolean popBackStackImmediate() {
executePendingTransactions();
}
public boolean popBackStackImmediate(String name, int flags) {
executePendingTransactions();
}
关于FragmentManager的讨论我们先暂时放一放,看一下BackStackRecord是怎么执行链表内部的操作的:
public void run() {
Op op = mHead;
while (op != null) {
switch(op.cmd) {
case OP_ADD:
Fragment f = op.fragment;
f.mNextAnim = op.enterAnim;
mManager.addFragment(f, false);
break;
case OP_REPLACE: {
Fragment f = op.fragment;
int containerId = f.mContainerId;
if (mManager.mAdded != null) {
if (old == f) {
op.fragment = f = null;
} else {
if (op.removed == null) {
op.removed = new ArrayList<Fragment>();
}
op.removed.add(old);
if (mAddToBackStack) {
old.mBackStackNesting += 1;
}
mManager.removeFragment(old, transition, transitionStyle);
}
}
if (f != null) {
f.addFragment(f, false);
}
break;
case xxx:
}
}
op = op.next;
}
mManager.moveToState(mManager.mCurState, mTransition, mTransitionStyle, true);
if (mAddToBackStack) {
mManager.addBackStackState(this);
}
}
我们来看一下FragmentManagerImpl对应的addFragment等操作:
public void addFragment(Fragment fragment, boolean moveToStateNow) {
makeActive(fragment);
if (!fragment.mDetached) {
if (mAdd.contains(fragment)) {
}
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);
}
fragment.mAdded = false;
fragment.mRemoving = true;
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.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); 这个方法才是 Fragment的核心,它的思想就是根据 Fragment 期望进入的状态和之前的状态进行对比,从而调用 Fragment相应的生命周期,那么问题就来,什么是期望进入的状态呢,我认为可以这么理解:
用户没有进行主动操作,但是 Fragment 和 FragmentManager的状态不一致,这时需要发生变化。 用户进行了主动操作,无论Fragment和 FragmentManager的状态是否一致,因为 Fragment 的状态发生了变化,因此这时也需要执行。 这里我们为了简便起见先看一下和生命周期有关的代码:
static final int INITIALIZING = 0;
static final int CREATED = 1;
static final int ACTIVITY_CREATED = 2;
static final int STOPPED = 3;
static final int STARTED = 4;
static final int RESUMED = 5;
void moveToState(int newState, int transit, int transitStyle, boolean always) {
if (!always && mCurState == newState) {
return;
}
mCurState = newState;
if (mActive != null) {
for (int i = 0; i < mActive.size; i++) {
Fragment f = mActive.get(i);
moveToState(f, newState, transit, transitStyle, false);
}
}
}
void moveToState(Fragment f, int newState, int transit, int transitionStyle, boolean keepActive) {
if (f.mState < newState) {
switch(f.mState) {
case Fragment.INITIALZING:
f.onAttach(mHost.getContext());
if (f.mParentFragment == null) {
mHost.onAttachFragment(f);
}
if (!f.mRetaining) {
f.performCreate(f.mSavedFragmentState);
}
if (f.mFromLayout) {
f.mView = f.performCreateView(f.getLayoutInflater(f.mSavedFragmentState), null, f.mSavedFragmentState);
if (f.mHidden) f.mView.setVisibility(View.GONE);
f.onViewCreated(f.mView, f.mSavedFragmentState);
}
case Fragment.CREATED:
if (newState > Fragment.CREATED) {
if (!f.mFromLayout) {
ViewGroup container = null;
if (f.mCotainerId != null) {
cotainer = (ViewGroup) mContainer.onFindViewById(f.mContainerId);
if (container == null && !f.mRestored) {
}
}
f.mContainer = container;
f.mView = f.performCreateView(f.getLayoutInflater(f.mSavedFragmentState), null, f.mSavedFragmentState);
if (f.mView != null) {
f.mInnerView = f.mView;
if (Build.VERSION.SDK >= 11) {
ViewCompact.setSaveFromParentEnable(f.mView, false);
} else {
f.mView = NoSaveStateFrameLayout.wap(f.mView);
}
if (f.mHidden) f.mView.setVisibility(View.GONE);
f.onViewCreated(f.mView, f.mSavedFragmentState);
} else {
f.mInnerView = null;
}
}
f.performActivityCreated(f.mSavedFragmentState);
}
case Fragment.ACTIVITY_CRREATED:
case Fragment.STOPPED:
if (newState > Fragment.STOPPED) {
f.performStart();
}
case Fragment.STARTED:
if (newState > Fragment.STARTED) {
f.performResume();
}
}
} else if (f.mState > newState) {
switch(f.mState) {
case Fragment.RESUMED:
if (newState < Fragment.RESUMED) {
f.performPause();
}
case Fragment.STARTED:
if (newState < Fragment.STARTED) {
f.performStop();
}
case Fragment.STOPPED::
if (newState < Fragment.STOPPED) {
f.performReallyStop();
}
case Fragment.ACTIVITY_CREATED:
if (newState < Fragment.ACTIVITY_CREATED) {
f.performDestroyView();
if (f.mView != null && f.mContainer != null) {
f.mContainer.removeView(f.mView);
}
}
case Fragment.CREATED:
if (newState < Fragment.CREATED) {
if (f.mAnimationAway != null) {
...
} else {
if (!f.mRetaining) {
f.performDestory();
} else {
f.mState = Fragment.INITIALIZING;
}
f.onDetach();
if (!f.mRetaining) {
makeInActive(f);
} else {
f.mHost = null;
f.mParentFragment = null;
f.mFragmentManager = null;
f.mChildFragmentManager = null;
}
}
}
}
}
到 moveToState方法中,我们看到了许多熟悉的面孔,就是我们平时最常谈到的 Fragment 的生命周期,通过这段代码我们就可以对它的生命周期有更加直观的理解。
|