FragmentManager
如下代码:通过supportFragmentManager和Activity进行关联起来
supportFragmentManager.beginTransaction()
.add()
.replace()
.remove()
.remove()
.add()
.addToBackStack()
.commit()
supportFramgentManager
后由谁提供的呢?从源码中可以看出是由FragmentController
提供的,FragmentController
是在FragmentActivity
创建的时候初始化的。
final FragmentController mFragments = FragmentController.createController(new HostCallbacks());
public FragmentManager getSupportFragmentManager() {
return mFragments.getSupportFragmentManager();
}
我们再看一下FragmentActivity的生命周期方法:如下代码都调用了mFragments
的dispatch方法,也就是说Fragment的生命周期管理委托给了FragmentController
。
@Override
protected void onStart() {
super.onStart();
....
mFragments.dispatchStart();
}
@Override
protected void onStop() {
super.onStop();
.....
mFragments.dispatchStop();
}
protected void onResumeFragments() {
mFragments.dispatchResume();
}
再来看FragmentController的代码,如下可以看到FragmentController
中的代码具体是FragmentHostCallback
来实现的
public class FragmentController {
private final FragmentHostCallback<?> mHost;
public static FragmentController createController(FragmentHostCallback<?> callbacks) {
return new FragmentController(callbacks);
}
private FragmentController(FragmentHostCallback<?> callbacks) {
mHost = callbacks;
}
public FragmentManager getSupportFragmentManager() {
return mHost.getFragmentManagerImpl();
}
....
}
在进入FragmentHostCallback
中创建了FragmentManager,注意Fragments may be hosted by any object
这句话,fragment可以由任何对象托管。也就是说fragment可以应用在任何地方不一定在Activity中。
/**
* Integration points with the Fragment host.
* <p>
* Fragments may be hosted by any object; such as an {@link Activity}. In order to
* host fragments, implement {@link FragmentHostCallback}, overriding the methods
* applicable to the host.
*/
public abstract class FragmentHostCallback<E> extends FragmentContainer {
@Nullable private final Activity mActivity;
@NonNull private final Context mContext;
@NonNull private final Handler mHandler;
private final int mWindowAnimations;
final FragmentManagerImpl mFragmentManager = new FragmentManagerImpl();
}
在FragmentActivity
类中,实现了FragmentHostCallback
抽象类:所以我们可以在Activity中管理fragment
class HostCallbacks extends FragmentHostCallback<FragmentActivity> {
public HostCallbacks() {
super(FragmentActivity.this /*fragmentActivity*/);
}
@Override
public void onDump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) {
FragmentActivity.this.dump(prefix, fd, writer, args);
}
@Override
public boolean onShouldSaveFragmentState(Fragment fragment) {
return !isFinishing();
}
}
FragmentTransaction
FragmentTransaction 对fragment进行事务操作,所谓事务就是一次性进行多个操作。
如下代码进行了多个操作:add replace remove等操作
supportFragmentManager.beginTransaction()
.add()
.replace()
.remove()
.remove()
.add()
.addToBackStack()
.commit()
在FragmentManager中的方法
@Override
public FragmentTransaction beginTransaction() {
return new BackStackRecord(this);
}
调用了BackStackRecord 继承了FragmentTransaction,在操作fragment回退栈的时候能够逆向执行事务,从而实现fragment的出栈操作。
/**
* Entry of an operation on the fragment back stack.
*/
final class BackStackRecord extends FragmentTransaction implements
FragmentManager.BackStackEntry, FragmentManagerImpl.OpGenerator {
......
}
事务操作就是在BackStackRecord中执行的,例如add操作,将fragment包装到Op包装类中,然后添加到list集合中,在提交事务的时候进行处理
//add 操作标记 OP_ADD
@Override
public FragmentTransaction add(Fragment fragment, @Nullable String tag) {
doAddOp(0, fragment, tag, OP_ADD);
return this;
}
//replace操作 标记OP_REPLACE 添加到集合汇总
@Override
public FragmentTransaction replace(int containerViewId, Fragment fragment,
@Nullable String tag) {
if (containerViewId == 0) {
throw new IllegalArgumentException("Must use non-zero containerViewId");
}
doAddOp(containerViewId, fragment, tag, OP_REPLACE);
return this;
}
//remove 操作 标记OP_REMOVE 添加到集合中
@Override
public FragmentTransaction remove(Fragment fragment) {
addOp(new Op(OP_REMOVE, fragment));
return this;
}
ArrayList<Op> mOps = new ArrayList<>();
//最终都调用了addOp方法
void addOp(Op op) {
mOps.add(op);
op.enterAnim = mEnterAnim;
op.exitAnim = mExitAnim;
op.popEnterAnim = mPopEnterAnim;
op.popExitAnim = mPopExitAnim;
}
下面来看一下,事务提交commit操作如何处理的:
@Override
public int commit() {
return commitInternal(false);
}
@Override
public int commitAllowingStateLoss() {
return commitInternal(true);
}
int commitInternal(boolean allowStateLoss) {
//如果mCommitted == true 抛出异常,对于一个事物提交最多只能调用一次
if (mCommitted) throw new IllegalStateException("commit already called");
//...
mCommitted = true;
if (mAddToBackStack) {
mIndex = mManager.allocBackStackIndex(this);
} else {
mIndex = -1;
}
mManager.enqueueAction(this, allowStateLoss);
return mIndex;
}
//mManager.enqueueAction(this, allowStateLoss);
//注意:allowStateLoss 标记
public void enqueueAction(OpGenerator action, boolean allowStateLoss) {
if (!allowStateLoss) {//allowStateLoss == false
checkStateLoss();
}
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<>();
}
mPendingActions.add(action);
scheduleCommit();
}
}
private void checkStateLoss() {
if (isStateSaved()) {
//如果宿主处于执行过onSaveInstanceState或者宿主处于stop状态 抛出如下异常
throw new IllegalStateException(
"Can not perform this action after onSaveInstanceState");
}
if (mNoTransactionsBecause != null) {
throw new IllegalStateException(
"Can not perform this action inside of " + mNoTransactionsBecause);
}
}
//checkStateLoss调用到如下方法
//这个方法就是判断 宿主是否执行过onSaveInstanceState或者宿主处于stop状态
@Override
public boolean isStateSaved() {
return mStateSaved || mStopped;
}
FragmentTrancation 4中提交方式
commit
(): 如果在宿主执行了onSaveInstanceState
之后再执行该操作,会抛出异常,属于异步事务(注意异步事务不是在子线程中执行,而是发送一条消息到消息队列中,当轮询到该消息才会执行)。commitAllowingStateLoss
():如果在宿主中执行了onSaveInstanceState之后再执行该操作,不会检查宿主的状态,不会抛出异常,该操作不会被Activity记录,恢复时也就没办法恢复这些提交操作,所以该操作使用不重要的事务(异步事务)commitNow
():会立刻执行当前提交的transaction事务。属于同步事务。commitNowAllowingStateLoss
() - 推荐使用 :具备以上两者的特性,即同步执行,也不会检查宿主的状态,有可能该操作不会被正确恢复。
异步事务(commit
和commitAllowingStateLoss
)提交最终会执行该方法:通过Handler发送到消息队列中
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);
}
}
}
/**
* Only call from main thread!
*/
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;
}
同步事务(commitNow
和commitNowAllowingStateLoss
)提交,则会执行如下方法:
public void execSingleAction(OpGenerator action, boolean allowStateLoss) {
if (allowStateLoss && (mHost == null || mDestroyed)) {
// This FragmentManager isn't attached, so drop the entire transaction.
return;
}
ensureExecReady(allowStateLoss);
if (action.generateOps(mTmpRecords, mTmpIsPop)) {
mExecutingActions = true;
try {
//移除事务的冗余操作以及执行事务
removeRedundantOperationsAndExecute(mTmpRecords, mTmpIsPop);
} finally {
cleanupExec();
}
}
doPendingDeferredStart();
burpActive();
}
removeRedundantOperationsAndExecute
是去掉事务的冗余操作如下代码.下面的这段add replace remove就是冗余操作,最终add-firstFragment.
.add(secondFragment)
.replace(threadFragment)
.remove(secondFragment)
.remove(threadFragment)
supportFragmentManager.beginTransaction()
.add(secondFragment)
.replace(threadFragment)
.remove(secondFragment)
.remove(threadFragment)
.add(firstFragment)
removeRedundantOperationsAndExecute
去掉事务后执行剩余的事务操作
private void removeRedundantOperationsAndExecute(ArrayList<BackStackRecord> records,
ArrayList<Boolean> isRecordPop) {
if (records == null || records.isEmpty()) {
return;
}
if (isRecordPop == null || records.size() != isRecordPop.size()) {
throw new IllegalStateException("Internal error with the back stack records");
}
// Force start of any postponed transactions that interact with scheduled transactions:
executePostponedTransaction(records, isRecordPop);
//依次执行事务操作
final int numRecords = records.size();
int startIndex = 0;
for (int recordNum = 0; recordNum < numRecords; recordNum++) {
final boolean canReorder = records.get(recordNum).mReorderingAllowed;
if (!canReorder) {
// execute all previous transactions
if (startIndex != recordNum) {
executeOpsTogether(records, isRecordPop, startIndex, recordNum);
}
// execute all pop operations that don't allow reordering together or
// one add operation
int reorderingEnd = recordNum + 1;
if (isRecordPop.get(recordNum)) {
while (reorderingEnd < numRecords
&& isRecordPop.get(reorderingEnd)
&& !records.get(reorderingEnd).mReorderingAllowed) {
reorderingEnd++;
}
}
executeOpsTogether(records, isRecordPop, recordNum, reorderingEnd);
startIndex = reorderingEnd;
recordNum = reorderingEnd - 1;
}
}
if (startIndex != numRecords) {
executeOpsTogether(records, isRecordPop, startIndex, numRecords);
}
}