先来看看 Fragment 的用法:
Fragment fragment = new Fragment();
FragmentManager fragmentManager = getFragmentManager();
FragmentTransaction transaction = fragmentManager.beginTransaction();
transaction.add(R.id.fragment_container, fragment);
transaction.commit();
然后一步步分析代码。
Activity.getFragmentManager()
public FragmentManager getFragmentManager() {
return mFragments.getFragmentManager();
}
接下来看看mFragments是什么?
final FragmentController mFragments = FragmentController.createController(new HostCallbacks());
mFragments是 Activity 的一个成员变量,构造它时,传入了一个HostCallbacks对象,先看FragmentController类。
public class FragmentController {
private final FragmentHostCallback<?> mHost;
public static final FragmentController createController(FragmentHostCallback<?> callbacks) {
return new FragmentController(callbacks);
}
private FragmentController(FragmentHostCallback<?> callbacks) {
mHost = callbacks;
}
//*************省略部分代码**********
}
而传入的HostCallbacks是 Activity 的一个内部类。
class HostCallbacks extends FragmentHostCallback<Activity> {
public HostCallbacks() {
super(Activity.this );
}
//*************省略部分代码**********
}
看看HostCallbacks的父类FragmentHostCallback构造方法做什么了
public abstract class FragmentHostCallback<E> extends FragmentContainer {
FragmentHostCallback(Activity 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;
}
//*************省略部分代码**********
}
由此可见,mFragments通过构造时传入HostCallbacks对象,从而持有了当前 Activity 的引用,并且还持有当前 Activity 的mHandler对象。
再加到mFragments.getFragmentManager()中去.
FragmentController.getFragmentManager()
public FragmentManager getFragmentManager() {
return mHost.getFragmentManagerImpl();
}
mHost对象就是刚刚的HostCallbacks,getFragmentManagerImpl的实现在HostCallbacks的父类FragmentHostCallback中
public abstract class FragmentHostCallback<E> extends FragmentContainer {
final FragmentManagerImpl mFragmentManager = new FragmentManagerImpl();
FragmentManagerImpl getFragmentManagerImpl() {
return mFragmentManager;
}
//*************省略部分代码**********
}
FragmentManagerImpl是FragmentManager的内部类,同时它还是FragmentManager的实现类。接下来看FragmentManager.beginTransaction(),直接看FragmentManager的实现类FragmentManagerImpl。
FragmentManagerImpl.beginTransaction()
@Override
public FragmentTransaction beginTransaction() {
return new BackStackRecord(this);
}
先看看BackStackRecord的构造方法
final class BackStackRecord extends FragmentTransaction implements
FragmentManager.BackStackEntry, Runnable {
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;
Op mHead;
Op mTail;
static final class Op {
Op next;
Op prev;
int cmd;
Fragment fragment;
int enterAnim;
int exitAnim;
int popEnterAnim;
int popExitAnim;
ArrayList<Fragment> removed;
}
public BackStackRecord(FragmentManagerImpl manager) {
mManager = manager;
}
//*************省略部分代码**********
}
可见,构造BackStackRecord时将FragmentManagerImpl(即:FragmentManager)传进来了。而BackStackRecord继承了FragmentTransaction并实现了Runnable接口。更重要的是BackStackRecord有一个名为Op的内部类,Op实现非常简单,就是一个双向链表的实现。
看完FragmentManager.beginTransaction(),接着看FragmentTransaction.add(R.id.fragment_container, fragment),直接看BackStackRecord即可;
public FragmentTransaction add(Fragment fragment, String tag) {
doAddOp(0, fragment, tag, OP_ADD);
return this;
}
public FragmentTransaction add(int containerViewId, Fragment fragment) {
doAddOp(containerViewId, fragment, null, OP_ADD);
return this;
}
public FragmentTransaction add(int containerViewId, Fragment fragment, String tag) {
doAddOp(containerViewId, fragment, tag, OP_ADD);
return this;
}
BackStackRecord有三个重载的 add 方法,最终都调用了doAddOp。
BackStackRecord.doAddOp(…)
private void doAddOp(int containerViewId, Fragment fragment, String tag, int opcmd) {
//将mManager的值赋给Fragment的mFragmentManager对象
fragment.mFragmentManager = mManager;
//对于同一个Fragment实例,变量 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;
}
//对于同一个Fragment实例,containerViewId也是不能改变的。
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_ADD)并将 Fragment 存起来,调用addOp()
Op op = new Op();
op.cmd = opcmd;
op.fragment = fragment;
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++;
}
addOp的操作比较简单,就是将新增的 Op对象加到当前的双向链表。其实FragmentTransaction的其它操作(repalce ,remove,sow,hide….)都是类似的,只是传入的操作类型不一样(即 Op.cmd)。接着看FragmentTransaction.commit()函数。
BackStackRecord.commit()
public int commit() {
return commitInternal(false);
}
commit()调用了commitInternal(false),传入的 boolean 值代表着是否允许状态丢失。另外一个commitAllowingStateLoss()方法调用的也是commitInternal,不过传入的是 true 而已。
int commitInternal(boolean allowStateLoss) {
//一个事务,只能提交一次
if (mCommitted) {
throw new IllegalStateException("commit already called");
}
//*************省略部分代码**********
mCommitted = true;
if (mAddToBackStack) {
mIndex = mManager.allocBackStackIndex(this);
} else {
mIndex = -1;
}
//又到了 FragmentManager 中了
mManager.enqueueAction(this, allowStateLoss);
return mIndex;
}
FragmentManager.enqueueAction
public void enqueueAction(Runnable action, boolean allowStateLoss) {
//如果不允许状态丢失,就进行状态检查,而检查的逻辑很简单:如果 此操作是在Activity的onSaveInstanceState调用了之后,onCreate 之前调用了,就报错
if (!allowStateLoss) {
checkStateLoss();
}
synchronized (this) {
if (mDestroyed || mHost == null) {
throw new IllegalStateException("Activity has been destroyed");
}
if (mPendingActions == null) {
mPendingActions = new ArrayList<Runnable>();
}
//将BackStackRecord加入一个ArrayList中
mPendingActions.add(action);
//如果是mPendingActions中只有当前的BackStackRecord,即mPendingActions之前是空的,则通过 Activity 的 Handler 发送一条消息,而mExecCommit是一个Runnable对象,它的 run 方法将被调用。
if (mPendingActions.size() == 1) {
mHost.getHandler().removeCallbacks(mExecCommit);
mHost.getHandler().post(mExecCommit);
}
}
}
Runnable mExecCommit = new Runnable() {
@Override
public void run() {
execPendingActions();
}
};
public boolean execPendingActions() {
if (mExecutingActions) {
throw new IllegalStateException("Recursive entry to executePendingTransactions");
}
if (Looper.myLooper() != mHost.getHandler().getLooper()) {
throw new IllegalStateException("Must be called from main thread of process");
}
boolean didSomething = false;
while (true) {
int numActions;
synchronized (this) {
//刚刚的BackStackRecord对象加入到了mPendingActions中
if (mPendingActions == null || mPendingActions.size() == 0) {
break;
}
//下面的逻辑很简单,就是从mPendingActions取出BackStackRecord,并调用它的 run 方法(之前已经提过BackStackRecord实现了 Runnable)
numActions = mPendingActions.size();
if (mTmpActions == null || mTmpActions.length < numActions) {
mTmpActions = new Runnable[numActions];
}
mPendingActions.toArray(mTmpActions);
mPendingActions.clear();
mHost.getHandler().removeCallbacks(mExecCommit);
}
mExecutingActions = true;
for (int i=0; i<numActions; i++) {
mTmpActions[i].run();
mTmpActions[i] = null;
}
mExecutingActions = false;
didSomething = true;
}
doPendingDeferredStart();
return didSomething;
}
又回到了BackStackRecord中了,看看BackStackRecord的 run方法。
BackStackRecord.run
public void run() {
if (FragmentManagerImpl.DEBUG) {
Log.v(TAG, "Run: " + this);
}
if (mAddToBackStack) {
if (mIndex < 0) {
throw new IllegalStateException("addToBackStack() called after commit()");
}
}
bumpBackStackNesting(1);
if (mManager.mCurState >= Fragment.CREATED) {
SparseArray<Fragment> firstOutFragments = new SparseArray<Fragment>();
SparseArray<Fragment> lastInFragments = new SparseArray<Fragment>();
calculateFragments(firstOutFragments, lastInFragments);
beginTransition(firstOutFragments, lastInFragments, false);
}
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: {
//Remove与 Add的结合体
Fragment f = op.fragment;
int containerId = f.mContainerId;
if (mManager.mAdded != null) {
for (int i = mManager.mAdded.size() - 1; i >= 0; i--) {
Fragment old = mManager.mAdded.get(i);
if (FragmentManagerImpl.DEBUG) {
Log.v(TAG,
"OP_REPLACE: adding=" + f + " old=" + old);
}
//必须是同一个 ContainerView
if (old.mContainerId == containerId) {
if (old == f) {
op.fragment = f = null;
} else {
if (op.removed == null) {
op.removed = new ArrayList<Fragment>();
}
op.removed.add(old);
old.mNextAnim = op.exitAnim;
if (mAddToBackStack) {
old.mBackStackNesting += 1;
if (FragmentManagerImpl.DEBUG) {
Log.v(TAG, "Bump nesting of "
+ old + " to " + old.mBackStackNesting);
}
}
mManager.removeFragment(old, mTransition, mTransitionStyle);
}
}
}
}
if (f != null) {
f.mNextAnim = op.enterAnim;
mManager.addFragment(f, false);
}
}
break;
case OP_REMOVE: {
Fragment f = op.fragment;
f.mNextAnim = op.exitAnim;
mManager.removeFragment(f, mTransition, mTransitionStyle);
}
break;
case OP_HIDE: {
Fragment f = op.fragment;
f.mNextAnim = op.exitAnim;
mManager.hideFragment(f, mTransition, mTransitionStyle);
}
break;
case OP_SHOW: {
Fragment f = op.fragment;
f.mNextAnim = op.enterAnim;
mManager.showFragment(f, mTransition, mTransitionStyle);
}
break;
case OP_DETACH: {
Fragment f = op.fragment;
f.mNextAnim = op.exitAnim;
mManager.detachFragment(f, mTransition, mTransitionStyle);
}
break;
case OP_ATTACH: {
Fragment f = op.fragment;
f.mNextAnim = op.enterAnim;
mManager.attachFragment(f, mTransition, mTransitionStyle);
}
break;
default: {
throw new IllegalArgumentException("Unknown cmd: " + op.cmd);
}
}
op = op.next;
}
mManager.moveToState(mManager.mCurState, mTransition,
mTransitionStyle, true);
//是否加入回退栈中,其实是加入FragmentManger的一个名为mBackStack的 ArrayList中管理。
if (mAddToBackStack) {
mManager.addBackStackState(this);
}
}
run方法对刚刚创建的双向链表进行操作,将刚刚加进去的操作一个个执行,最终的执行工作都交给了mManager对象,以 ADD 为例,最终是调用了 mManager.addFragment(f, false)。
FragmentManger.addFragment(…)
public void addFragment(Fragment fragment, boolean moveToStateNow) {
if (mAdded == null) {
mAdded = new ArrayList<Fragment>();
}
//将 Fragment中加入到一个名为mActive的ArrayList中进行管理
makeActive(fragment);
if (!fragment.mDetached) {
if (mAdded.contains(fragment)) {
throw new IllegalStateException("Fragment already added: " + fragment);
}
//设置一些状态,加入到一个名为mAdded的ArrayList中进行管理
mAdded.add(fragment);
fragment.mAdded = true;
fragment.mRemoving = false;
//是否支持菜单栏
if (fragment.mHasMenu && fragment.mMenuVisible) {
mNeedMenuInvalidate = true;
}
//刚刚传进来的moveToStateNow是 false,那什么时候执行呢 moveToState(fragment)?
//其实刚刚BackStackRecord 的 run 方法最后调用了 mManager.moveToState(mManager.mCurState, mTransition,mTransitionStyle, true)。
if (moveToStateNow) {
moveToState(fragment);
}
}
}
而不管那个moveToState方法,最终都会调用moveToState(int newState, int transit, int transitStyle, boolean always, boolean keepActive)这个有5个参数的方法中去。
FragmentManger.moveToState(…)
void moveToState(Fragment f, int newState, int transit, int transitionStyle,
boolean keepActive) {
//****************省略部分代码****************
//生命周期的正序(onAttach--->onCreate)
if (f.mState < newState) {
//****************省略部分代码****************
switch (f.mState) {
case Fragment.INITIALIZING:
if (DEBUG) Log.v(TAG, "moveto CREATED: " + f);
if (f.mSavedFragmentState != null) {
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;
}
}
}
//将 FragmentHostCallback<Activity> 设置给 Fragment的 mHost
f.mHost = mHost;
//如果是 Activity中的 Fragment 则mParent为 null
f.mParentFragment = mParent;
//设置FragmentManager
f.mFragmentManager = mParent != null
? mParent.mChildFragmentManager : mHost.getFragmentManagerImpl();
f.mCalled = false;
//调用 Fragment的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);
}
if (!f.mRetaining) {
//调用 Fragment的onCreate()方法
f.performCreate(f.mSavedFragmentState);
} else {
f.restoreChildFragmentState(f.mSavedFragmentState, true);
f.mState = Fragment.CREATED;
}
f.mRetaining = false;
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.mView.setSaveFromParentEnabled(false);
if (f.mHidden) f.mView.setVisibility(View.GONE);
f.onViewCreated(f.mView, f.mSavedFragmentState);
}
}
case Fragment.CREATED:
if (newState > Fragment.CREATED) {
if (DEBUG) Log.v(TAG, "moveto ACTIVITY_CREATED: " + f);
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;
f.mView = f.performCreateView(f.getLayoutInflater(
f.mSavedFragmentState), container, f.mSavedFragmentState);
if (f.mView != null) {
f.mView.setSaveFromParentEnabled(false);
if (container != null) {
Animator anim = loadAnimator(f, transit, true,
transitionStyle);
if (anim != null) {
anim.setTarget(f.mView);
setHWLayerAnimListenerIfAlpha(f.mView, anim);
anim.start();
}
container.addView(f.mView);
}
if (f.mHidden) f.mView.setVisibility(View.GONE);
f.onViewCreated(f.mView, f.mSavedFragmentState);
}
}
f.performActivityCreated(f.mSavedFragmentState);
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();
}
case Fragment.STARTED:
if (newState > Fragment.STARTED) {
if (DEBUG) Log.v(TAG, "moveto RESUMED: " + f);
f.performResume();
// Get rid of this in case we saved it and never needed it.
f.mSavedFragmentState = null;
f.mSavedViewState = null;
}
}
}
//Fragment 再次加到前台,生命周期的逆序
else if (f.mState > newState) {
//****************省略部分代码****************
}
}
moveToState方法特别的长,其实就是根据 Fragmenti当着的状态值去更新相应的状态,也就是管理着 Fragment 的生命周期。Activity通过 FragmentManager 将自己的生命周期与 Fragment 同步,最终也都会调用 moveToState。
Fragment.startActivity()
无论是startActivity还是startActivityForResult,最终都会调用FragmentActivity的startActivityFromFragment
public class FragmentActivity extends BaseFragmentActivityHoneycomb implements
ActivityCompat.OnRequestPermissionsResultCallback,
ActivityCompatApi23.RequestPermissionsRequestCodeValidator {
public void startActivityFromFragment(Fragment fragment, Intent intent,
int requestCode) {
if (requestCode == -1) {
super.startActivityForResult(intent, -1);
return;
}
if ((requestCode&0xffff0000) != 0) {
throw new IllegalArgumentException("Can only use lower 16 bits for requestCode");
}
//其实是对requestCode进行了特殊处理(位运算)
super.startActivityForResult(intent, ((fragment.mIndex+1)<<16) + (requestCode&0xffff));
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
mFragments.noteStateNotSaved();
//结果回来时对requestCode进行了反向操作,看看是不是 Fragment启动的
int index = requestCode>>16;
if (index != 0) {
index--;
final int activeFragmentsCount = mFragments.getActiveFragmentsCount();
if (activeFragmentsCount == 0 || index < 0 || index >= activeFragmentsCount) {
Log.w(TAG, "Activity result fragment index out of range: 0x"
+ Integer.toHexString(requestCode));
return;
}
final List<Fragment> activeFragments =
mFragments.getActiveFragments(new ArrayList<Fragment>(activeFragmentsCount));
Fragment frag = activeFragments.get(index);
if (frag == null) {
Log.w(TAG, "Activity result no fragment exists for index: 0x"
+ Integer.toHexString(requestCode));
} else {
frag.onActivityResult(requestCode&0xffff, resultCode, data);
}
return;
}
super.onActivityResult(requestCode, resultCode, data);
}
}
哈哈,这种做法比较取巧,但如果设置一个比较特殊的 requestCode,说不定正好能匹配上一个Fragment呢?