相信大家平时用到很多Fragment, 手机平板的代码共用,各种东西的复用,用Fragment也很方便。如今Fragment遍布在我们的APP里面,今天此文将讲解Activity是如何Fragment机制联动的,以及各个生命周期是如何走的,因为,说实话,Fragment的生命周期足够复杂,我们需要知道它的各个生命周期是如何被调用的。
今天涉及到的类(本文基于Android8.1源码):
// Activity类, AMS控制的生命周期都是回调给Activity
frameworks/base/core/java/android/app/Activity.java
// Fragment,被实现对象,被回调生命周期对象
frameworks/base/core/java/android/app/Fragment.java
// FragmentController 其实是一个代理类,代理FragmentManager那些方法
frameworks/base/core/java/android/app/FragmentController.java
// FragmentHostCallback 这是一个抽象类,需要主体实现,里面实现一些Fragment机制中所不能实现的功能,比如请求权限,这些都需要主体来实现
frameworks/base/core/java/android/app/FragmentHostCallback.java
// Fragment的管理类,被FragmentHostCallback持有,负责控制Fragment的状态,真正做操作的类
frameworks/base/core/java/android/app/FragmentManager.java
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 {
...
}
}
从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 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 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 mPendingActions;
boolean mExecutingActions;
int mNextFragmentIndex = 0;
SparseArray mActive;
final ArrayList mAdded = new ArrayList<>();
ArrayList mBackStack;
ArrayList mCreatedMenus;
// Must be accessed while locked.
ArrayList mBackStackIndices;
ArrayList mAvailBackStackIndices;
ArrayList mBackStackChangeListeners;
final CopyOnWriteArrayList>
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 mTmpRecords;
ArrayList mTmpIsPop;
ArrayList mTmpAddedFragments;
// Temporary vars for state save and restore.
Bundle mStateBundle = null;
SparseArray mStateArray = null;
// Postponed transactions.
ArrayList 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 = getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.main_fragment_container, homeFragment);
transaction.commit();
我们来看下beginTransaction方法的实现
@Override
public FragmentTransaction beginTransaction() {
return new BackStackRecord(this);
}
可以见到,其返回了一个BackStackRecord类,那么这个类是继承于FragmentTransaction的
/**
* @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 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 mCommitRunnables;
int mBreadCrumbTitleRes;
CharSequence mBreadCrumbTitleText;
int mBreadCrumbShortTitleRes;
CharSequence mBreadCrumbShortTitleText;
ArrayList mSharedElementSourceNames;
ArrayList mSharedElementTargetNames;
我们从其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方法的逻辑,在这里就负责取出各个事务进行操作。
Fragment expandOps(ArrayList 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;
}
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;
}
....
}
其他的生命周期也是类似的,大体都一样
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的生命周期如下
结尾
520这天,写了这篇博客。。。嗯 希望大家多多进步
本文作者:Anderson/Jerey_Jobs
博客地址 : http://jerey.cn/
地址 : Anderson大码渣
github地址 : https://github.com/Jerey-Jobs