FragmentManager源码简单分析
我们对Fragment的用法已经再熟悉不过了, 对Fragment不了解建议去了解了解, 毕竟是基础; 博客对Fragment的使用方法讲解的非常之多, 但是对源码分析的却寥寥无几, 最近公司项目需要一个框架, 跟Activity 和 Fragment 比较像, 所以选择了Fragment来参考.
废话不多说, 下面我们一步一步通过使用Fragment的步骤来分析源码:
在Activity中 我们通过 getFragmentManager()获取到一个 FragmentManager对象,这是一个抽象内, 真正使用的FragmentManager是它的实现类FragmentManagerImpl
final class FragmentManagerImpl extends FragmentManager {}
然后我们会通过 FragmentManager.beginTransaction() 来获取一个FragmentTransaction对象, 我们对Fragment的add() remove() show() 等操作都是通过这个对象来完成的.
public FragmentTransaction beginTransaction() {
return new BackStackRecord(this);
}
我们看到这里返回了一个 BackStackRecord对象, 并把FragmentManager自己作为构造传递过去, 这个对象肯定就是 FragmentTransaction 的子类, 从名字可以看去就是对Fragment的一个记录器.
然后我们找一个最熟悉的方法来分析, add() 来添加一个Fragment.
public FragmentTransaction add(int containerViewId, Fragment fragment) {
doAddOp(containerViewId, fragment, null, OP_ADD);
return this;
}
这里调用了doAddOp() 方法,并指定命令(操作) 为 OP_ADD, 我们来看看这里面干了什么玩意.
private void doAddOp(int containerViewId, Fragment fragment, String tag, int opcmd) {
fragment.mFragmentManager = mManager;
/**
这里一小段代码主要做了一些判断 判断当前的tag, containerViewId 是 否和 Fragment中的tag, containerViewId是否相同
**/
Op op = new Op();
op.cmd = opcmd;
op.fragment = fragment;
addOp(op);
}
这里new了一个 op对象, 并将操作命令赋值给op.cmd, 当前要操作的Fragment赋值给op.Fragment, 我们看看OP是个什么鬼
static final class Op {
Op next;
Op prev;
int cmd;
Fragment fragment;
int enterAnim;
int exitAnim;
int popEnterAnim;
int popExitAnim;
ArrayList<Fragment> removed;
}
这个类很简单, 使用了一个链表的结构, 将一些属性进行了封装. 上面的方法最后调用了addOp(op) 的方法, 不多说, 过去看看干了什么.
void addOp(Op op) {
if (mHead == null) {
mHead = mTail = op;
} else {
op.prev = mTail;
mTail.next = op;
mTail = op;
}
op.enterAnim = mEnterAnim;
op.exitAnim = mExitAnim;
op.popEnterAnim = mPopEnterAnim;
op.popExitAnim = mPopExitAnim;
mNumOp++;
}
好失望, 貌似什么也没有干, 就是将OP对象的属性进行赋值, Y_Y 等等, 不要忘了, 在我们对Fragment操作后, 都会调用 FragmentTransaction.commit()方法, 赶紧过去瞅瞅.
public int commit() {
return commitInternal(false);
}
这里调用了 commitInternal(false) .
int commitInternal(boolean allowStateLoss) {
/**
没用的代码干掉
**/
mCommitted = true;
if (mAddToBackStack) {
mIndex = mManager.allocBackStackIndex(this);
} else {
mIndex = -1;
}
//mManager 就是FragmentManager对象, 看方法名Action应该就是处理Fragment的操作
mManager.enqueueAction(this, allowStateLoss);
return mIndex;
}
回到FragmentManagerImpl, 找到 enqueueAction()方法
public void enqueueAction(Runnable action, boolean allowStateLoss)
第一个参数是一个Runnable对象, 而当时调用的时候使用的是 this, 也就是 BackStackRecord自己,回过头看看 确实实现了 Runnable接口; 第二个参数不用管, 当时传过来的是false. 看看具体代码
public void enqueueAction(Runnable 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<Runnable>();
}
//将当前的Runnable对象,也就是 BackStackRecord添加到一个集合中去.
mPendingActions.add(action);
if (mPendingActions.size() == 1) {
mHost.getHandler().removeCallbacks(mExecCommit);
//是用handler.post() 发出了一个消息
mHost.getHandler().post(mExecCommit);
}
}
}
看看 mExecCommit是一个什么玩意
Runnable mExecCommit = new Runnable() {
@Override
public void run() {
execPendingActions();
}
};
内部执行了 execPendingActions() 方法
这里面的代码比较多, 节省空间 抽出核心代码
//看着像一个死循环, 不要被吓到 下面还有个break呢.
while (true) {
int numActions;
synchronized (this) {
if (mPendingActions == null || mPendingActions.size() == 0) {
break;
}
numActions = mPendingActions.size();
//这里重新使用了一个数组对 Runnable对象 也就是BackStackRecord进行存储
if (mTmpActions == null || mTmpActions.length < numActions) {
mTmpActions = new Runnable[numActions];
}
mPendingActions.toArray(mTmpActions);
//清空就满足上面的break条件了
mPendingActions.clear();
mHost.getHandler().removeCallbacks(mExecCommit);
}
mExecutingActions = true;
for (int i=0; i<numActions; i++) {
//调用了run()方法
mTmpActions[i].run();
mTmpActions[i] = null;
}
mExecutingActions = false;
didSomething = true;
}
让我们回去看看 BackStackRecord中 的run() 方法做了什么鬼操作
//这里又是一堆代码, 但是看到这里貌似已经豁然开朗了. 我们来挑一个来看看
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;
}
op = op.next;
}
}
这里依然是一个while循环, 也就是对链表 OP对象 逐一进行处理, 挑了我们眼熟的OP_ADD, 是不是很眼熟, 这里又回到FragmentManager中调用了 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.mHasMenu && fragment.mMenuVisible) {
mNeedMenuInvalidate = true;
}
if (moveToStateNow) {
//这里最后调用了moveToState()方法
moveToState(fragment);
}
}
}
void moveToState(Fragment f) {
//调用了5个参数的方法
moveToState(f, mCurState, 0, 0, false);
}
void moveToState(Fragment f, int newState, int transit, int transitionStyle,
boolean keepActive) {
//这里的代码真是太多了!!! Y_Y就不贴了
}
至此Fragment的生命周期的方法调用都是在上面这个方法( moveToState ) 中操作的, 应该是使用了状态模式, 看的我晕晕乎乎的.