本文章来详细的跟踪一下关于fragment的相关的API和源码分析。
我们可以带着几个疑问来看fragment
- fragment是如何与activity进行关联的
- fragment生命周期与activity的生命周期的同步
- fragment是如何加入进去的
我们通常会在activity中这样来添加fragment
supportFragmentManager.beginTransaction().add(R.id.fragment_container, fragment).commit()
fragment涉及到几个核心的类:
FragmentManager 实现类是 FragmentManagerImpl
FragmentTransaction 实现类是 BackStackRecord
一、Activity是如何跟Fragment进行关联的
在FragmentActivity类中有一个成员变量
FragmentActivity.java
final FragmentController mFragments = FragmentController.createController(new HostCallbacks());
里面包含了两个类:FragmentController、HostCallbacks
1、FragmentController
这个类的主要作用是存储了mHosts对象,以及对生命周期变化时的分发。
FragmentController.java
private final FragmentHostCallback<?> mHost;
@NonNull
public static FragmentController createController(@NonNull FragmentHostCallback<?> callbacks) {
return new FragmentController(checkNotNull(callbacks, "callbacks == null"));
}
public void attachHost(@Nullable Fragment parent) {
mHost.mFragmentManager.attachController(
mHost, mHost /*container*/, parent);
}
public void dispatchCreate() {
mHost.mFragmentManager.dispatchCreate();
}
public void dispatchActivityCreated() {
mHost.mFragmentManager.dispatchActivityCreated();
}
public void dispatchStart() {
mHost.mFragmentManager.dispatchStart();
}
public void dispatchResume() {
mHost.mFragmentManager.dispatchResume();
}
通过代码可以看出,这个类没有实际的实现代码,将所有的方法都分发给了mHost.mFragmentManager 那继续分析mHost是什么意思
2、HostCallbacks
HostCallbacks 是FragmentActivity的内部类 而这个类继承自FragmentHostCallback
FragmentActivity.java
class HostCallbacks extends FragmentHostCallback<FragmentActivity> implements
ViewModelStoreOwner,
OnBackPressedDispatcherOwner {
public HostCallbacks() {
super(FragmentActivity.this /*fragmentActivity*/);
}
继续看FragmentHostCallback干啥的 第一眼望去,就看到了它
FragmentHostCallback.java
final FragmentManager mFragmentManager = new FragmentManagerImpl();
3、那基本上就可以梳理一下了。
1.FragmentActivity 内部有一个成员变量mFragments 是FragmentController对象
2.FragmentController 内部包含一个成员变量mHost,和生命周期相关的方法。都是由mHost来分发的。是FragmentHostCallback对象
3.FragmentHostCallback 内部有一个成员变量mFragmentManager 是FragmentManager对象。
所以最终的具体实现还是回到了FragmentManager上面。
一个Activity 只能有一个FragmentManager
那我们知道了FragmentManager在FragmentActivity创建时创建的。那Activity又是什么时候创建的呢?
二、Fragment的生命周期
这就涉及到了Activity的创建流程,这里简单进行跟踪,主要是分析Fragment的生命周期与Activity的同步。
这里先引入一张图,来说明Activity、FragmentManager、Fragment三个之间的生命周期的关系
接着从Activity的创建流程出发来分析。
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
...
activity = mInstrumentation.newActivity(cl, component.getClassName(),r.intent);
...
}
在newActivity()方法内部会创建 activity对象, 此时 FragmentManager 对象也会被创建。
1.attach()
接着看attach()方法的调用,也是在performLaunchActivity方法里面
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
...
activity = mInstrumentation.newActivity(cl, component.getClassName(),r.intent);
...
activity.attach(...)
...
}
在activity创建后,紧接着调用了attach()方法
final void attach() {
....
mFragments.attachHost(null /*parent*/);
...
}
这里终于看到了fragment相关的代码了。上面我们知道,mFragment是FragmentActivity创建的时候所创建的全局变量
而attachHost()方法也最后到了这里
public void attachHost(@Nullable Fragment parent) {
mHost.mFragmentManager.attachController(
mHost, mHost /*container*/, parent);
}
void attachController(@NonNull FragmentHostCallback<?> host,
@NonNull FragmentContainer container, @Nullable final Fragment parent) {
if (mHost != null) throw new IllegalStateException("Already attached");
mHost = host;
mContainer = container;
mParent = parent;
....
}
其实可以看到,没有做实际的工作,就是初始化的操作。
2.onCreate()
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
...
activity = mInstrumentation.newActivity(cl, component.getClassName(), r.intent);
...
activity.attach(...)
...
if (r.isPersistable()) {
mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
} else {
mInstrumentation.callActivityOnCreate(activity, r.state);
}
}
继续看callActivityOnCreate方法
public void callActivityOnCreate(Activity activity, Bundle icicle, PersistableBundle persistentState) {
prePerformCreate(activity);
activity.performCreate(icicle, persistentState);
postPerformCreate(activity);
}
具体看activity.performCreate(icicle, persistentState);
final void performCreate(Bundle icicle, PersistableBundle persistentState) {
...
if (persistentState != null) {
onCreate(icicle, persistentState);
} else {
onCreate(icicle);
}
...
mFragments.dispatchActivityCreated();
...
}
又看到fragment相关的代码了,但是别急,onCreate方法里也有。
mFragments.dispatchCreate();
也就是说在activity onCreate方法调用时,fragment调用了两个生命周期。 分别是
dispatchCreate()
dispatchActivityCreated()
接着继续分析这两个方法
void dispatchCreate() {
mStateSaved = false;
mStopped = false;
dispatchStateChange(Fragment.CREATED);
}
void dispatchActivityCreated() {
mStateSaved = false;
mStopped = false;
dispatchStateChange(Fragment.ACTIVITY_CREATED);
}
里面都调用了dispatchStateChange方法,而且还有Fragment的静态成员变量。 先看看Fragment的静态成员变量都有哪些
Fragment.java
static final int INITIALIZING = -1; // Not yet attached.
static final int ATTACHED = 0; // Attached to the host.
static final int CREATED = 1; // Created.
static final int ACTIVITY_CREATED = 2; // Fully created, not started.
static final int STARTED = 3; // Created and started, not resumed.
static final int RESUMED = 4; // Created started and resumed.
一共是有5个,默认是-1 继续看dispagchStateChange方法
private void dispatchStateChange(int nextState) {
try {
mExecutingActions = true;
mFragmentStore.dispatchStateChange(nextState);
moveToState(nextState, false);
} finally {
mExecutingActions = false;
}
execPendingActions(true);
}
最主要还是看moveToState方法
void moveToState(int newState, boolean always) {
...
mCurState = newState;
...
for (Fragment f : mFragmentStore.getFragments()) {
moveFragmentToExpectedState(f);
}
}
由此分析出,只要做了两个关键动作,将状态赋值给mCurState,并且遍历fragments,做movestate操作 到最后最后,还是执行了这个方法,里面代码很多,主要就是将fragment的生命周期进行调用。
void moveToState(@NonNull Fragment f, int newState) {
}
三、Fragment是怎么加入进来的
要说怎么加入进来的,那就从我们通常添加操作的方法入手。
supportFragmentManager.beginTransaction().add(R.id.fragment_container, fragment).commit()
1.supportFragmentManager
跟进去看这个supportFragmentManager是什么东西
FragmentActivity.java
@NonNull
public FragmentManager getSupportFragmentManager() {
return mFragments.getSupportFragmentManager();
}
FragmentController.java
@NonNull
public FragmentManager getSupportFragmentManager() {
return mHost.mFragmentManager;
}
从前面的分析我们可以看到,supportFragmentManager其实就是fragmentManager
2、beginTransaction()
@NonNull
public FragmentTransaction beginTransaction() {
return new BackStackRecord(this);
}
FragmentTransaction类是做啥用的呢?
1、定义了Op对象,用于保存fragment对象和layoutid
2、定义了mOps队列用于保存Op对象
3、提供了add、replace等方法
3、add(layoutId,fragment)
跟踪源代码
FragmentTransction.java
@NonNull
public FragmentTransaction add(@IdRes int containerViewId, @NonNull Fragment fragment) {
doAddOp(containerViewId, fragment, null, OP_ADD);
return this;
}
FragmentTransction.java
void doAddOp(int containerViewId, Fragment fragment, @Nullable String tag, int opcmd) {
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.");
}
//1.根据tag来创建
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;
}
//2.将rootid传递进来
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;
}
//3.添加
addOp(new Op(opcmd, fragment));
}
Op 就是保存有fragment和一些动画的属性
FragmentTransction.java
static final class Op {
int mCmd;
Fragment mFragment;
int mEnterAnim;
int mExitAnim;
int mPopEnterAnim;
int mPopExitAnim;
Lifecycle.State mOldMaxState;
Lifecycle.State mCurrentMaxState;
Op() {
}
addOp 方法就是把fragment layoutId 等封装好的Op 加入到mOps队列中
FragmentTransction.java
void addOp(Op op) {
mOps.add(op);
op.mEnterAnim = mEnterAnim;
op.mExitAnim = mExitAnim;
op.mPopEnterAnim = mPopEnterAnim;
op.mPopExitAnim = mPopExitAnim;
}
mOps就是一个List集合
FragmentTransction.java
ArrayList<Op> mOps = new ArrayList<>();
将fragment等信息保存到集合中之后,是在什么时候取出来的呢? 这个时候就到了commit()方法了。 继续跟踪
4、commit()
commit方法是FragemtnTrasation调用的,实现类是BackStackRecord.
FragmentTransction.java
public abstract int commit();
@Override
public int commit() {
return commitInternal(false);
}
int commitInternal(boolean allowStateLoss) {
if (mCommitted) throw new IllegalStateException("commit already called");
if (FragmentManager.isLoggingEnabled(Log.VERBOSE)) {
Log.v(TAG, "Commit: " + this);
LogWriter logw = new LogWriter(TAG);
PrintWriter pw = new PrintWriter(logw);
dump(" ", pw);
pw.close();
}
mCommitted = true;
if (mAddToBackStack) {
mIndex = mManager.allocBackStackIndex();
} else {
mIndex = -1;
}
//1.最后调用到了FragmentManager类中
mManager.enqueueAction(this, allowStateLoss);
return mIndex;
}
void enqueueAction(@NonNull OpGenerator action, boolean allowStateLoss) {
////省略几行代码
synchronized (mPendingActions) {
if (mHost == null) {
if (allowStateLoss) {
// This FragmentManager isn't attached, so drop the entire transaction.
return;
}
throw new IllegalStateException("Activity has been destroyed");
}
mPendingActions.add(action);
scheduleCommit();
}
}
void scheduleCommit() {
synchronized (mPendingActions) {
boolean postponeReady =
mPostponedTransactions != null && !mPostponedTransactions.isEmpty();
boolean pendingReady = mPendingActions.size() == 1;
if (postponeReady || pendingReady) {
//1.由此可见,是抛到主线程做的具体的操作
mHost.getHandler().removeCallbacks(mExecCommit);
mHost.getHandler().post(mExecCommit);
updateOnBackPressedCallbackEnabled();
}
}
}
private Runnable mExecCommit = new Runnable() {
@Override
public void run() {
execPendingActions(true);
}
};
boolean execPendingActions(boolean allowStateLoss) {
ensureExecReady(allowStateLoss);
boolean didSomething = false;
while (generateOpsForPendingActions(mTmpRecords, mTmpIsPop)) {
mExecutingActions = true;
try {
removeRedundantOperationsAndExecute(mTmpRecords, mTmpIsPop);
} finally {
cleanupExec();
}
didSomething = true;
}
updateOnBackPressedCallbackEnabled();
doPendingDeferredStart();
mFragmentStore.burpActive();
return didSomething;
}
最后走到了这里
FragmentManager.java
private void executeOpsTogether(@NonNull ArrayList<BackStackRecord> records,
@NonNull ArrayList<Boolean> isRecordPop, int startIndex, int endIndex) {
////省略几行代码
executeOps(records, isRecordPop, startIndex, endIndex);
////省略几行代码
}
最后走到了BackStackRecord的executePop方法内
void executePopOps(boolean moveToState) {
for (int opNum = mOps.size() - 1; opNum >= 0; opNum--) {
final Op op = mOps.get(opNum);
Fragment f = op.mFragment;
if (f != null) {
f.setNextTransition(FragmentManager.reverseTransit(mTransition));
}
switch (op.mCmd) {
case OP_ADD:
f.setNextAnim(op.mPopExitAnim);
mManager.setExitAnimationOrder(f, true);
mManager.removeFragment(f);
break;
case OP_REMOVE:
f.setNextAnim(op.mPopEnterAnim);
mManager.addFragment(f);
break;
case OP_HIDE:
f.setNextAnim(op.mPopEnterAnim);
mManager.showFragment(f);
break;
case OP_SHOW:
f.setNextAnim(op.mPopExitAnim);
mManager.setExitAnimationOrder(f, true);
mManager.hideFragment(f);
break;
case OP_DETACH:
f.setNextAnim(op.mPopEnterAnim);
mManager.attachFragment(f);
break;
case OP_ATTACH:
f.setNextAnim(op.mPopExitAnim);
mManager.setExitAnimationOrder(f, true);
mManager.detachFragment(f);
break;
case OP_SET_PRIMARY_NAV:
mManager.setPrimaryNavigationFragment(null);
break;
case OP_UNSET_PRIMARY_NAV:
mManager.setPrimaryNavigationFragment(f);
break;
case OP_SET_MAX_LIFECYCLE:
mManager.setMaxLifecycle(f, op.mOldMaxState);
break;
default:
throw new IllegalArgumentException("Unknown cmd: " + op.mCmd);
}
if (!mReorderingAllowed && op.mCmd != OP_REMOVE && f != null) {
mManager.moveFragmentToExpectedState(f);
}
}
if (!mReorderingAllowed && moveToState) {
mManager.moveToState(mManager.mCurState, true);
}
}
里面做了两个操作,1、添加或者移除fragment 2、moveToState