一、介紹
Fragment 表示在FragmentActivity中的行為或節(jié)面的一部分茸时,具有自己的生命周期贡定,但是他的生命周期是受宿主Activity的生命周期影響的,且必須依托在Activity中可都。
每一個Fragment都有自己的生命周期缓待,布局和行為蚓耽,那么在使用Fragment的時候,盡量的將其采用復(fù)用式的設(shè)計旋炒,這樣可以將Fragment加入到多個Activity中去步悠,但是要盡量避免通過一個Fragment去操作另外一個Fragment.。
二瘫镇、簡單使用:
public class FragmentMainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_fragment_main)
val beginTransaction = supportFragmentManager.beginTransaction()
beginTransaction.add(R.id.topcontent, TopFragment())
beginTransaction.replace(R.id.bottomcontent, BottomFragment())
beginTransaction.commit()
}
//下面是Fragment狀態(tài)保存流程的入庫
override fun onSaveInstanceState(outState: Bundle, outPersistentState: PersistableBundle) {
super.onSaveInstanceState(outState, outPersistentState)
}
}
三鼎兽、原理分析:
本文中的原理分析都是基于上述簡單使用部分的代碼進(jìn)行的。
3.1铣除、生命周期
1)從Activity的onCreate()開始尚粘,直接進(jìn)入super.onCreate()
//AppCompatActivity.java
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
final AppCompatDelegate delegate = getDelegate();
delegate.installViewFactory();
delegate.onCreate(savedInstanceState);
super.onCreate(savedInstanceState);//繼續(xù)從這里進(jìn)入父類的onCreate()
}
//FragmentActivity.java
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//這里給Fragment一個生命周期是Activity的oncreate
mFragmentLifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_CREATE);
//開始調(diào)用fragment的dispatchCreate()
mFragments.dispatchCreate();
}
//FragmentController.java
public void dispatchCreate() {
mHost.mFragmentManager.dispatchCreate();
}
2)FragmentManagerImpl分發(fā)Fragment的生命周期狀態(tài)
FragmentManagerImpl 是繼承自FragmentManager 钳降,所以是通過FragmentManagerImpl對象直接調(diào)用父類的dispatchCreate(),直接進(jìn)入的是FragmentManager.java的dispatchCreate
//FragmentManager.java
void dispatchCreate() {
mStateSaved = false;
mStopped = false;
mNonConfig.setIsStateSaved(false);
//特別注意參數(shù)傳入的是Fragment.Created
dispatchStateChange(Fragment.CREATED);
}
private void dispatchStateChange(int nextState) {
try {
mExecutingActions = true;
//這里保存了當(dāng)前Fragment的狀態(tài)
mFragmentStore.dispatchStateChange(nextState);
//第一個參數(shù)是Fragment.CREATE ,第二個參數(shù)是false
moveToState(nextState, false);
if (USE_STATE_MANAGER) {
Set<SpecialEffectsController> controllers = collectAllSpecialEffectsController();
for (SpecialEffectsController controller : controllers) {
controller.forceCompleteAllOperations();
}
}
} finally {
mExecutingActions = false;
}
execPendingActions(true);
}
void moveToState(int newState, boolean always) {
if (mHost == null && newState != Fragment.INITIALIZING) {
//因?yàn)閙Host不為null ,所以這個分支不會進(jìn)來
throw new IllegalStateException("No activity");
}
if (!always && newState == mCurState) {
//int mCurState = Fragment.INITIALIZING; 但是newState 傳遞進(jìn)來的是Fragment_ONCREATE 撵幽,所以這個分支也不會進(jìn)來
return;
}
//這時候mCurState 也變成Fragment.ONCREATE
mCurState = newState;
if (USE_STATE_MANAGER) {
mFragmentStore.moveToExpectedState();
} else {
// Must add them in the proper order. mActive fragments may be out of order
for (Fragment f : mFragmentStore.getFragments()) {
moveFragmentToExpectedState(f);
}
// Now iterate through all active fragments. These will include those that are removed
// and detached.
for (FragmentStateManager fragmentStateManager :
mFragmentStore.getActiveFragmentStateManagers()) {
Fragment f = fragmentStateManager.getFragment();
if (!f.mIsNewlyAdded) {
moveFragmentToExpectedState(f);
}
boolean beingRemoved = f.mRemoving && !f.isInBackStack();
if (beingRemoved) {
mFragmentStore.makeInactive(fragmentStateManager);
}
}
}
startPendingDeferredFragments();
if (mNeedMenuInvalidate && mHost != null && mCurState == Fragment.RESUMED) {
mHost.onSupportInvalidateOptionsMenu();
mNeedMenuInvalidate = false;
}
}
void moveFragmentToExpectedState(@NonNull Fragment f) {
if (!mFragmentStore.containsActiveFragment(f.mWho)) {
if (isLoggingEnabled(Log.DEBUG)) {
Log.d(TAG, "Ignoring moving " + f + " to state " + mCurState
+ "since it is not added to " + this);
}
return;
}
moveToState(f);
if (f.mView != null) {
if (f.mIsNewlyAdded && f.mContainer != null) {
// Make it visible and run the animations
if (f.mPostponedAlpha > 0f) {
f.mView.setAlpha(f.mPostponedAlpha);
}
f.mPostponedAlpha = 0f;
f.mIsNewlyAdded = false;
// run animations:
FragmentAnim.AnimationOrAnimator anim = FragmentAnim.loadAnimation(
mHost.getContext(), f, true, f.getPopDirection());
if (anim != null) {
if (anim.animation != null) {
f.mView.startAnimation(anim.animation);
} else {
anim.animator.setTarget(f.mView);
anim.animator.start();
}
}
}
}
if (f.mHiddenChanged) {
completeShowHideFragment(f);
}
}
void moveToState(@NonNull Fragment f) {
moveToState(f, mCurState);
}
3)Fragment生命周期變化
1、switch case語句沒有break ,這樣就會從匹配的case依次執(zhí)行
2、通過fragmentStateManager了對應(yīng)生命周期的方法域蜗;
3、在switch case 外層的if else 語句是針對Fragment的狀態(tài)從create到resume ,然后從resume到ondestory的兩個方向的狀態(tài)
//FragmentManager.java
void moveToState(@NonNull Fragment f, int newState) {
FragmentStateManager fragmentStateManager = mFragmentStore.getFragmentStateManager(f.mWho);
if (fragmentStateManager == null) {
// Ideally, we only call moveToState() on active Fragments. However,
// in restoreSaveState() we can call moveToState() on retained Fragments
// just to clean them up without them ever being added to mActive.
// For these cases, a brand new FragmentStateManager is enough.
fragmentStateManager = new FragmentStateManager(mLifecycleCallbacksDispatcher,
mFragmentStore, f);
// Only allow this FragmentStateManager to go up to CREATED at the most
fragmentStateManager.setFragmentManagerState(Fragment.CREATED);
}
// When inflating an Activity view with a resource instead of using setContentView(), and
// that resource adds a fragment using the <fragment> tag (i.e. from layout and in layout),
// the fragment will move to the VIEW_CREATED state before the fragment manager
// moves to CREATED. So when moving the fragment manager moves to CREATED and the
// inflated fragment is already in VIEW_CREATED we need to move new state up from CREATED
// to VIEW_CREATED. This avoids accidentally moving the fragment back down to CREATED
// which would immediately destroy the Fragment's view. We rely on computeExpectedState()
// to pull the state back down if needed.
if (f.mFromLayout && f.mInLayout && f.mState == Fragment.VIEW_CREATED) {
newState = Math.max(newState, Fragment.VIEW_CREATED);
}
newState = Math.min(newState, fragmentStateManager.computeExpectedState());
if (f.mState <= newState) {
// If we are moving to the same state, we do not need to give up on the animation.
if (f.mState < newState && !mExitAnimationCancellationSignals.isEmpty()) {
// The fragment is currently being animated... but! Now we
// want to move our state back up. Give up on waiting for the
// animation and proceed from where we are.
cancelExitAnimation(f);
}
switch (f.mState) {
case Fragment.INITIALIZING:
if (newState > Fragment.INITIALIZING) {
fragmentStateManager.attach();
}
// fall through
case Fragment.ATTACHED:
if (newState > Fragment.ATTACHED) {
fragmentStateManager.create();
}
// fall through
case Fragment.CREATED:
// We want to unconditionally run this anytime we do a moveToState that
// moves the Fragment above INITIALIZING, including cases such as when
// we move from CREATED => CREATED as part of the case fall through above.
if (newState > Fragment.INITIALIZING) {
fragmentStateManager.ensureInflatedView();
}
if (newState > Fragment.CREATED) {
fragmentStateManager.createView();
}
// fall through
case Fragment.VIEW_CREATED:
if (newState > Fragment.VIEW_CREATED) {
fragmentStateManager.activityCreated();
}
// fall through
case Fragment.ACTIVITY_CREATED:
if (newState > Fragment.ACTIVITY_CREATED) {
fragmentStateManager.start();
}
// fall through
case Fragment.STARTED:
if (newState > Fragment.STARTED) {
fragmentStateManager.resume();
}
}
} else if (f.mState > newState) {
switch (f.mState) {
case Fragment.RESUMED:
if (newState < Fragment.RESUMED) {
fragmentStateManager.pause();
}
// fall through
case Fragment.STARTED:
if (newState < Fragment.STARTED) {
fragmentStateManager.stop();
}
// fall through
case Fragment.ACTIVITY_CREATED:
if (newState < Fragment.ACTIVITY_CREATED) {
if (isLoggingEnabled(Log.DEBUG)) {
Log.d(TAG, "movefrom ACTIVITY_CREATED: " + f);
}
if (f.mView != null) {
// Need to save the current view state if not
// done already.
if (mHost.onShouldSaveFragmentState(f) && f.mSavedViewState == null) {
fragmentStateManager.saveViewState();
}
}
}
// fall through
case Fragment.VIEW_CREATED:
if (newState < Fragment.VIEW_CREATED) {
FragmentAnim.AnimationOrAnimator anim = null;
if (f.mView != null && f.mContainer != null) {
// Stop any current animations:
f.mContainer.endViewTransition(f.mView);
f.mView.clearAnimation();
// If parent is being removed, no need to handle child animations.
if (!f.isRemovingParent()) {
if (mCurState > Fragment.INITIALIZING && !mDestroyed
&& f.mView.getVisibility() == View.VISIBLE
&& f.mPostponedAlpha >= 0) {
anim = FragmentAnim.loadAnimation(mHost.getContext(),
f, false, f.getPopDirection());
}
f.mPostponedAlpha = 0;
// Robolectric tests do not post the animation like a real device
// so we should keep up with the container and view in case the
// fragment view is destroyed before we can remove it.
ViewGroup container = f.mContainer;
View view = f.mView;
if (anim != null) {
FragmentAnim.animateRemoveFragment(f, anim,
mFragmentTransitionCallback);
}
container.removeView(view);
if (FragmentManager.isLoggingEnabled(Log.VERBOSE)) {
Log.v(FragmentManager.TAG, "Removing view " + view + " for "
+ "fragment " + f + " from container " + container);
}
// If the local container is different from the fragment
// container, that means onAnimationEnd was called, onDestroyView
// was dispatched and the fragment was already moved to state, so
// we should early return here instead of attempting to move to
// state again.
if (container != f.mContainer) {
return;
}
}
}
// If a fragment has an exit animation (or transition), do not destroy
// its view immediately and set the state after animating
if (mExitAnimationCancellationSignals.get(f) == null) {
fragmentStateManager.destroyFragmentView();
}
}
// fall through
case Fragment.CREATED:
if (newState < Fragment.CREATED) {
if (mExitAnimationCancellationSignals.get(f) != null) {
// We are waiting for the fragment's view to finish animating away.
newState = Fragment.CREATED;
} else {
fragmentStateManager.destroy();
}
}
// fall through
case Fragment.ATTACHED:
if (newState < Fragment.ATTACHED) {
fragmentStateManager.detach();
}
}
}
if (f.mState != newState) {
if (isLoggingEnabled(Log.DEBUG)) {
Log.d(TAG, "moveToState: Fragment state for " + f + " not updated inline; "
+ "expected state " + newState + " found " + f.mState);
}
f.mState = newState;
}
}
//FragmentStateManager.java
void attach() {
mFragment.mHost = mFragment.mFragmentManager.getHost();
mFragment.mParentFragment = mFragment.mFragmentManager.getParent();
mDispatcher.dispatchOnFragmentPreAttached(mFragment, false);
mFragment.performAttach();//**********************
mDispatcher.dispatchOnFragmentAttached(mFragment, false);
}
void create() {
if (FragmentManager.isLoggingEnabled(Log.DEBUG)) {
Log.d(TAG, "moveto CREATED: " + mFragment);
}
if (!mFragment.mIsCreated) {
mDispatcher.dispatchOnFragmentPreCreated(
mFragment, mFragment.mSavedFragmentState, false);
mFragment.performCreate(mFragment.mSavedFragmentState);//********
mDispatcher.dispatchOnFragmentCreated(
mFragment, mFragment.mSavedFragmentState, false);
} else {
mFragment.restoreChildFragmentState(mFragment.mSavedFragmentState);
mFragment.mState = Fragment.CREATED;
}
}
void createView() {
//********
mFragment.performCreateView(layoutInflater, container, mFragment.mSavedFragmentState);
if (mFragment.mView != null) {
mFragment.mView.setSaveFromParentEnabled(false);
mFragment.mView.setTag(R.id.fragment_container_view_tag, mFragment);
//*******************
mFragment.performViewCreated();
mDispatcher.dispatchOnFragmentViewCreated(
mFragment, mFragment.mView, mFragment.mSavedFragmentState, false);
int postOnViewCreatedVisibility = mFragment.mView.getVisibility();
float postOnViewCreatedAlpha = mFragment.mView.getAlpha();
}
mFragment.mState = Fragment.VIEW_CREATED;
}
void activityCreated() {
if (FragmentManager.isLoggingEnabled(Log.DEBUG)) {
Log.d(TAG, "moveto ACTIVITY_CREATED: " + mFragment);
}
//**********************
mFragment.performActivityCreated(mFragment.mSavedFragmentState);
mDispatcher.dispatchOnFragmentActivityCreated(
mFragment, mFragment.mSavedFragmentState, false);
}
void start() {
if (FragmentManager.isLoggingEnabled(Log.DEBUG)) {
Log.d(TAG, "moveto STARTED: " + mFragment);
}
//**********************
mFragment.performStart();
mDispatcher.dispatchOnFragmentStarted(mFragment, false);
}
void resume() {
if (FragmentManager.isLoggingEnabled(Log.DEBUG)) {
Log.d(TAG, "moveto RESUMED: " + mFragment);
}
View focusedView = mFragment.getFocusedView();
if (focusedView != null && isFragmentViewChild(focusedView)) {
boolean success = focusedView.requestFocus();
if (FragmentManager.isLoggingEnabled(Log.VERBOSE)) {
Log.v(FragmentManager.TAG, "requestFocus: Restoring focused view "
+ focusedView + " " + (success ? "succeeded" : "failed") + " on Fragment "
+ mFragment + " resulting in focused view " + mFragment.mView.findFocus());
}
}
mFragment.setFocusedView(null);
mFragment.performResume(); //**********************
mDispatcher.dispatchOnFragmentResumed(mFragment, false);
mFragment.mSavedFragmentState = null;
mFragment.mSavedViewState = null;
mFragment.mSavedViewRegistryState = null;
}
相信走到這里哥谷,對Fragment的生命周期的理解有了“柳暗花明"的感覺了吧。
3.2、事務(wù)處理流程
了解了Fragment的生命周期后报破,接著使用示例中的通過事務(wù)來進(jìn)行加載fragment的事務(wù)處理過程。先來看看下圖熟悉一下:
1)開始事務(wù)beginTransaction
//FragmentManager.java
public FragmentTransaction beginTransaction() {
//這里創(chuàng)建一個回退棧
return new BackStackRecord(this);
}
public FragmentFactory getFragmentFactory() {
if (mFragmentFactory != null) {
return mFragmentFactory;
}
if (mParent != null) {
// This can't call setFragmentFactory since we need to
// compute this each time getFragmentFactory() is called
// so that if the parent's FragmentFactory changes, we
// pick the change up here.
return mParent.mFragmentManager.getFragmentFactory();
}
return mHostFragmentFactory;
}
private FragmentFactory mHostFragmentFactory = new FragmentFactory() {
@SuppressWarnings("deprecation")
@NonNull
@Override
public Fragment instantiate(@NonNull ClassLoader classLoader, @NonNull String className) {
return getHost().instantiate(getHost().getContext(), className, null);
}
};
//BackStackRecord.java
final class BackStackRecord extends FragmentTransaction implements
FragmentManager.BackStackEntry, FragmentManager.OpGenerator {
//構(gòu)造方法
BackStackRecord(@NonNull FragmentManager manager) {
super(manager.getFragmentFactory(), manager.getHost() != null
? manager.getHost().getContext().getClassLoader()
: null);
mManager = manager;
}
}
//FragmentTransaction.java
public abstract class FragmentTransaction {
FragmentTransaction(@NonNull FragmentFactory fragmentFactory,
@Nullable ClassLoader classLoader) {
mFragmentFactory = fragmentFactory;
mClassLoader = classLoader;
}
}
2)添加Fragment事務(wù)
//FragmentTransaction.java
public FragmentTransaction add(@IdRes int containerViewId, @NonNull Fragment fragment) {
//注意第四個參數(shù)的值
doAddOp(containerViewId, fragment, null, OP_ADD);
return this;
}
void doAddOp(int containerViewId, Fragment fragment, @Nullable String tag, int opcmd) {
final Class<?> fragmentClass = fragment.getClass();
final int modifiers = fragmentClass.getModifiers();
//此處省略異常檢測代碼
if (containerViewId != 0) {
//此處省略異常檢測代碼
fragment.mContainerId = fragment.mFragmentId = containerViewId;
}
addOp(new Op(opcmd, fragment));
}
//在數(shù)組中存放組裝好的數(shù)據(jù)結(jié)構(gòu)
ArrayList<Op> mOps = new ArrayList<>();
void addOp(Op op) {
mOps.add(op);
op.mEnterAnim = mEnterAnim;
op.mExitAnim = mExitAnim;
op.mPopEnterAnim = mPopEnterAnim;
op.mPopExitAnim = mPopExitAnim;
}
//靜態(tài)內(nèi)部類:將Fragment與Fragment的操作指令組裝成一個新的數(shù)據(jù)結(jié)構(gòu)
static final class Op {
int mCmd;
Fragment mFragment;
int mEnterAnim;
int mExitAnim;
int mPopEnterAnim;
int mPopExitAnim;
Lifecycle.State mOldMaxState;
Lifecycle.State mCurrentMaxState;
Op() {
}
Op(int cmd, Fragment fragment) {
this.mCmd = cmd;
this.mFragment = fragment;
this.mOldMaxState = Lifecycle.State.RESUMED;
this.mCurrentMaxState = Lifecycle.State.RESUMED;
}
Op(int cmd, @NonNull Fragment fragment, Lifecycle.State state) {
this.mCmd = cmd;
this.mFragment = fragment;
this.mOldMaxState = fragment.mMaxState;
this.mCurrentMaxState = state;
}
}
3)替換Fragment事務(wù)
//FragmentTransaction.java
public FragmentTransaction replace(@IdRes int containerViewId, @NonNull Fragment fragment) {
return replace(containerViewId, fragment, null);
}
public FragmentTransaction replace(@IdRes int containerViewId, @NonNull Fragment fragment,
@Nullable String tag) {
if (containerViewId == 0) {
throw new IllegalArgumentException("Must use non-zero containerViewId");
}
//注意第四個參數(shù)的值
doAddOp(containerViewId, fragment, tag, OP_REPLACE);
return this;
}
//這里和添加事務(wù)走的是同一個地方,不同的是第四個參數(shù)opcmd不一樣爆价,
void doAddOp(int containerViewId, Fragment fragment, @Nullable String tag, int opcmd) {
final Class<?> fragmentClass = fragment.getClass();
final int modifiers = fragmentClass.getModifiers();
//此處省略了檢測異常的代碼
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;
}
addOp(new Op(opcmd, fragment));
}
//后續(xù)的調(diào)用就和添加事務(wù)一致了
4)事務(wù)提交
事務(wù)提交有下面幾種方式:
- commit() 中異步執(zhí)行芬膝,不允許在Activity保存狀態(tài)之后調(diào)用
- commitAllowingStateLoss() 異步執(zhí)行,允許在Activity保存狀態(tài)之后調(diào)用
- commitNow() 同步執(zhí)行钾唬,不允許在Activity保存狀態(tài)之后調(diào)用
- commitNowAllowingStateLoss() 異步執(zhí)行檩坚,允許在Activity保存狀態(tài)之后調(diào)用
先來看看這四個提交事務(wù)方法的源碼:
//BackStackRecord.java
@Override
public int commit() {
return commitInternal(false);
}
@Override
public int commitAllowingStateLoss() {
return commitInternal(true);
}
@Override
public void commitNow() {
disallowAddToBackStack();
mManager.execSingleAction(this, false);
}
@Override
public void commitNowAllowingStateLoss() {
disallowAddToBackStack();
mManager.execSingleAction(this, true);
}
下面以commit()為例進(jìn)行源碼分析:
FragmentTransaction是一個抽象類,而上面的回退棧BackStackRecord就是他的實(shí)現(xiàn)類,那么FragmentTransaction調(diào)用commit的時候岭参,實(shí)際上是調(diào)用回退棧BackStackRecord的commit方法反惕。
//BackStackRecord.java
public int commit() {
return commitInternal(false);
}
//這個方法傳入的參數(shù)是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;
}
//這里會調(diào)用FragmentManager的enqueueAction----> this 當(dāng)前的回退棧,allowStateLoss 是參數(shù)傳入的false
mManager.enqueueAction(this, allowStateLoss);
return mIndex;
}
//FragmentManager.java
void enqueueAction(@NonNull OpGenerator action, boolean allowStateLoss) {
if (!allowStateLoss) {
if (mHost == null) {
if (mDestroyed) {
throw new IllegalStateException("FragmentManager has been destroyed");
} else {
throw new IllegalStateException("FragmentManager has not been attached to a "
+ "host.");
}
}
//由于allowStateLoss 傳入的是false,會進(jìn)入該分支執(zhí)行演侯,這個方法僅僅做了檢查姿染,那么就會接著進(jìn)入下面同步代碼塊
checkStateLoss();
}
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) {
mHost.getHandler().removeCallbacks(mExecCommit);
//mExecCommit是一個runnable
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 {
//1. 真正實(shí)現(xiàn)事務(wù)處理的地方
removeRedundantOperationsAndExecute(mTmpRecords, mTmpIsPop);
} finally {
cleanupExec();
}
didSomething = true;
}
updateOnBackPressedCallbackEnabled();
//2. 執(zhí)行延遲啟動
doPendingDeferredStart();
mFragmentStore.burpActive();
return didSomething;
}
//1 >>>>>>>>>>>>>>>>>>>>
private void removeRedundantOperationsAndExecute(@NonNull ArrayList<BackStackRecord> records,
@NonNull ArrayList<Boolean> isRecordPop) {
// 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) {
//進(jìn)入
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);
}
}
private void executeOpsTogether(@NonNull ArrayList<BackStackRecord> records,
@NonNull ArrayList<Boolean> isRecordPop, int startIndex, int endIndex) {
//此處省略了很多代碼
executeOps(records, isRecordPop, startIndex, endIndex);
if (USE_STATE_MANAGER) {
// The last operation determines the overall direction, this ensures that operations
// such as push, push, pop, push are correctly considered a push
boolean isPop = isRecordPop.get(endIndex - 1);
// Ensure that Fragments directly affected by operations
// are moved to their expected state in operation order
for (int index = startIndex; index < endIndex; index++) {
BackStackRecord record = records.get(index);
if (isPop) {
// Pop operations get applied in reverse order
for (int opIndex = record.mOps.size() - 1; opIndex >= 0; opIndex--) {
FragmentTransaction.Op op = record.mOps.get(opIndex);
Fragment fragment = op.mFragment;
if (fragment != null) {
FragmentStateManager fragmentStateManager =
createOrGetFragmentStateManager(fragment);
fragmentStateManager.moveToExpectedState();
}
}
} else {
for (FragmentTransaction.Op op : record.mOps) {
Fragment fragment = op.mFragment;
if (fragment != null) {
FragmentStateManager fragmentStateManager =
createOrGetFragmentStateManager(fragment);
fragmentStateManager.moveToExpectedState();
}
}
}
}
// And only then do we move all other fragments to the current state
moveToState(mCurState, true);
} else {
int postponeIndex = endIndex;
if (postponeIndex != startIndex && allowReordering) {
// need to run something now
if (mCurState >= Fragment.CREATED) {
FragmentTransition.startTransitions(mHost.getContext(), mContainer,
records, isRecordPop, startIndex,
postponeIndex, true, mFragmentTransitionCallback);
}
moveToState(mCurState, true);
}
}
if (addToBackStack) {
reportBackStackChanged();
}
}
private static void executeOps(@NonNull ArrayList<BackStackRecord> records,
@NonNull ArrayList<Boolean> isRecordPop, int startIndex, int endIndex) {
for (int i = startIndex; i < endIndex; i++) {
final BackStackRecord record = records.get(i);
final boolean isPop = isRecordPop.get(i);
if (isPop) {
record.bumpBackStackNesting(-1);
// Only execute the add operations at the end of
// all transactions.
boolean moveToState = i == (endIndex - 1);
record.executePopOps(moveToState);
} else {
record.bumpBackStackNesting(1);
record.executeOps();
}
}
}
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.setPopDirection(true);
f.setAnimations(op.mEnterAnim, op.mExitAnim, op.mPopEnterAnim, op.mPopExitAnim);
f.setNextTransition(FragmentManager.reverseTransit(mTransition));
// Reverse the target and source names for pop operations
f.setSharedElementNames(mSharedElementTargetNames, mSharedElementSourceNames);
}
switch (op.mCmd) {
case OP_ADD:
mManager.setExitAnimationOrder(f, true);
mManager.removeFragment(f);
break;
case OP_REMOVE:
mManager.addFragment(f);
break;
case OP_HIDE:
mManager.showFragment(f);
break;
case OP_SHOW:
mManager.setExitAnimationOrder(f, true);
mManager.hideFragment(f);
break;
case OP_DETACH:
mManager.attachFragment(f);
break;
case OP_ATTACH:
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) {
if (!FragmentManager.USE_STATE_MANAGER) {
mManager.moveFragmentToExpectedState(f);
}
}
}
if (!mReorderingAllowed && moveToState && !FragmentManager.USE_STATE_MANAGER) {
mManager.moveToState(mManager.mCurState, true);
}
}
//2.>>>>>>>>>>>>>>>>>>>>>>>>
private void doPendingDeferredStart() {
if (mHavePendingDeferredStart) {
mHavePendingDeferredStart = false;
//啟動延期的Fragments
startPendingDeferredFragments();
}
}
private void startPendingDeferredFragments() {
for (FragmentStateManager fragmentStateManager :
mFragmentStore.getActiveFragmentStateManagers()) {
performPendingDeferredStart(fragmentStateManager);
}
}
void performPendingDeferredStart(@NonNull FragmentStateManager fragmentStateManager) {
Fragment f = fragmentStateManager.getFragment();
if (f.mDeferStart) {
if (mExecutingActions) {
// Wait until we're done executing our pending transactions
mHavePendingDeferredStart = true;
return;
}
f.mDeferStart = false;
//下面if else 語句中的兩個方法在fragment的生命周期中是非常面熟的
if (USE_STATE_MANAGER) {
//下面這個方法和moveToState()有點(diǎn)區(qū)別
fragmentStateManager.moveToExpectedState();
} else {
//下面就會進(jìn)入Fragment的生命周期變化的方法中了,這里最后也是會走進(jìn)FragmentStateManager中去
moveToState(f);
}
}
}
//FragmentStateManager.java
void moveToExpectedState() {
if (mMovingToState) {
if (FragmentManager.isLoggingEnabled(Log.VERBOSE)) {
Log.v(FragmentManager.TAG, "Ignoring re-entrant call to "
+ "moveToExpectedState() for " + getFragment());
}
return;
}
try {
mMovingToState = true;
int newState;
while ((newState = computeExpectedState()) != mFragment.mState) {
if (newState > mFragment.mState) {
// Moving upward
int nextStep = mFragment.mState + 1;
switch (nextStep) {
case Fragment.ATTACHED:
attach();
break;
case Fragment.CREATED:
create();
break;
case Fragment.VIEW_CREATED:
ensureInflatedView();
createView();
break;
case Fragment.AWAITING_EXIT_EFFECTS:
activityCreated();
break;
case Fragment.ACTIVITY_CREATED:
if (mFragment.mView != null && mFragment.mContainer != null) {
SpecialEffectsController controller = SpecialEffectsController
.getOrCreateController(mFragment.mContainer,
mFragment.getParentFragmentManager());
int visibility = mFragment.mView.getVisibility();
SpecialEffectsController.Operation.State finalState =
SpecialEffectsController.Operation.State.from(visibility);
controller.enqueueAdd(finalState, this);
}
mFragment.mState = Fragment.ACTIVITY_CREATED;
break;
case Fragment.STARTED:
start();
break;
case Fragment.AWAITING_ENTER_EFFECTS:
mFragment.mState = Fragment.AWAITING_ENTER_EFFECTS;
break;
case Fragment.RESUMED:
resume();
break;
}
} else {
// Moving downward
int nextStep = mFragment.mState - 1;
switch (nextStep) {
case Fragment.AWAITING_ENTER_EFFECTS:
pause();
break;
case Fragment.STARTED:
mFragment.mState = Fragment.STARTED;
break;
case Fragment.ACTIVITY_CREATED:
stop();
break;
case Fragment.AWAITING_EXIT_EFFECTS:
if (FragmentManager.isLoggingEnabled(Log.DEBUG)) {
Log.d(TAG, "movefrom ACTIVITY_CREATED: " + mFragment);
}
if (mFragment.mView != null) {
// Need to save the current view state if not done already
// by saveInstanceState()
if (mFragment.mSavedViewState == null) {
saveViewState();
}
}
if (mFragment.mView != null && mFragment.mContainer != null) {
SpecialEffectsController controller = SpecialEffectsController
.getOrCreateController(mFragment.mContainer,
mFragment.getParentFragmentManager());
controller.enqueueRemove(this);
}
mFragment.mState = Fragment.AWAITING_EXIT_EFFECTS;
break;
case Fragment.VIEW_CREATED:
mFragment.mInLayout = false;
mFragment.mState = Fragment.VIEW_CREATED;
break;
case Fragment.CREATED:
destroyFragmentView();
mFragment.mState = Fragment.CREATED;
break;
case Fragment.ATTACHED:
destroy();
break;
case Fragment.INITIALIZING:
detach();
break;
}
}
}
if (FragmentManager.USE_STATE_MANAGER && mFragment.mHiddenChanged) {
if (mFragment.mView != null && mFragment.mContainer != null) {
// Get the controller and enqueue the show/hide
SpecialEffectsController controller = SpecialEffectsController
.getOrCreateController(mFragment.mContainer,
mFragment.getParentFragmentManager());
if (mFragment.mHidden) {
controller.enqueueHide(this);
} else {
controller.enqueueShow(this);
}
}
if (mFragment.mFragmentManager != null) {
mFragment.mFragmentManager.invalidateMenuForFragment(mFragment);
}
mFragment.mHiddenChanged = false;
mFragment.onHiddenChanged(mFragment.mHidden);
}
} finally {
mMovingToState = false;
}
}
代碼走到這里就進(jìn)入了Fragment的生命周期中了秒际,后續(xù)打源碼可以到3.1的第三步中繼續(xù)跟蹤了悬赏。
3.3、Fragment保存與恢復(fù)流程
1)保存
Fragment的保存主要會經(jīng)過6個步驟來完成:
保存View及childview
保存當(dāng)前Fragment的索引娄徊,
將Fragment保存到數(shù)組闽颇,
保存回退棧信息,
保存前面保存的數(shù)據(jù)到FragmentManagerState寄锐,
保存非配置信息
經(jīng)常上述六步就完成了Fragment的保存過程了兵多,下面跟著源碼來走一下這個流程:
//Fragment的保存從Activity 的onSaveInstanceState開始,
override fun onSaveInstanceState(outState: Bundle, outPersistentState: PersistableBundle) {
super.onSaveInstanceState(outState, outPersistentState)
}
public void onSaveInstanceState(@NonNull Bundle outState,
@NonNull PersistableBundle outPersistentState) {
onSaveInstanceState(outState);
}
protected void onSaveInstanceState(@NonNull Bundle outState) {
outState.putBundle(WINDOW_HIERARCHY_TAG, mWindow.saveHierarchyState());
outState.putInt(LAST_AUTOFILL_ID, mLastAutofillId);
//這里保存Fragment的所有狀態(tài)橄仆,并且返回一個Parcelable
Parcelable p = mFragments.saveAllState();
if (p != null) {
outState.putParcelable(FRAGMENTS_TAG, p);
}
if (mAutoFillResetNeeded) {
outState.putBoolean(AUTOFILL_RESET_NEEDED, true);
getAutofillManager().onSaveInstanceState(outState);
}
dispatchActivitySaveInstanceState(outState);
}
//FragmentController.java
public Parcelable saveAllState() {
//這里會進(jìn)去FragmentManagerImpl對象的saveAllState,也就是父類FragmentManager的該方法中
return mHost.mFragmentManager.saveAllState();
}
//FragmentManager.java
Parcelable saveAllState() {
// Make sure all pending operations have now been executed to get
// our state update-to-date.
forcePostponedTransactions();
endAnimatingAwayFragments();
execPendingActions();
//狀態(tài)保存的標(biāo)記
mStateSaved = true;
mSavedNonConfig = null;
if (mActive == null || mActive.size() <= 0) {
return null;
}
// First collect all active fragments.
int N = mActive.size();
FragmentState[] active = new FragmentState[N];
boolean haveFragments = false;
for (int i=0; i<N; i++) {
//找到處于活躍狀態(tài)的Fragment: mActive是一個SparseArray數(shù)組,這里后續(xù)會在性能優(yōu)化的數(shù)據(jù)結(jié)構(gòu)優(yōu)化中詳細(xì)介紹
Fragment f = mActive.valueAt(i);
if (f != null) {
if (f.mIndex < 0) {
throwException(new IllegalStateException(
"Failure saving state: active " + f
+ " has cleared index: " + f.mIndex));
}
haveFragments = true;
//FragmentState是一個Parcelable的數(shù)據(jù)模型盆顾,用來存放Fragment的相關(guān)信息
FragmentState fs = new FragmentState(f);
active[i] = fs;
if (f.mState > Fragment.INITIALIZING && fs.mSavedFragmentState == null) {
//第一步:saveFragmentBasicState()保存是哪些基礎(chǔ)狀態(tài)呢怠褐??您宪?奈懒?
fs.mSavedFragmentState = saveFragmentBasicState(f);
if (f.mTarget != null) {
if (f.mTarget.mIndex < 0) {
throwException(new IllegalStateException(
"Failure saving state: " + f
+ " has target not in fragment manager: " + f.mTarget));
}
if (fs.mSavedFragmentState == null) {
fs.mSavedFragmentState = new Bundle();
}
//第二步:將Fragment的索引保存到Bundler中
putFragment(fs.mSavedFragmentState,
FragmentManagerImpl.TARGET_STATE_TAG, f.mTarget);
if (f.mTargetRequestCode != 0) {
fs.mSavedFragmentState.putInt(
FragmentManagerImpl.TARGET_REQUEST_CODE_STATE_TAG,
f.mTargetRequestCode);
}
}
} else {
fs.mSavedFragmentState = f.mSavedFragmentState;
}
if (DEBUG) Log.v(TAG, "Saved state of " + f + ": "
+ fs.mSavedFragmentState);
}
}
if (!haveFragments) {
if (DEBUG) Log.v(TAG, "saveAllState: no fragments!");
return null;
}
int[] added = null;
BackStackState[] backStack = null;
// Build list of currently added fragments. 第三步將當(dāng)前Fragment保存到數(shù)組中
N = mAdded.size();
if (N > 0) {
added = new int[N];
for (int i=0; i<N; i++) {
added[i] = mAdded.get(i).mIndex;
if (added[i] < 0) {
throwException(new IllegalStateException(
"Failure saving state: active " + mAdded.get(i)
+ " has cleared index: " + added[i]));
}
if (DEBUG) Log.v(TAG, "saveAllState: adding fragment #" + i
+ ": " + mAdded.get(i));
}
}
//第四步 Now save back stack. 保存回退棧信息
if (mBackStack != null) {
N = mBackStack.size();
if (N > 0) {
backStack = new BackStackState[N];
for (int i=0; i<N; i++) {
backStack[i] = new BackStackState(this, mBackStack.get(i));
if (DEBUG) Log.v(TAG, "saveAllState: adding back stack #" + i
+ ": " + mBackStack.get(i));
}
}
}
//第五步:將保存的Fragment和回退棧信息保存到FragmentManagerState中
FragmentManagerState fms = new FragmentManagerState();
fms.mActive = active;
fms.mAdded = added;
fms.mBackStack = backStack;
fms.mNextFragmentIndex = mNextFragmentIndex;
if (mPrimaryNav != null) {
fms.mPrimaryNavActiveIndex = mPrimaryNav.mIndex;
}
//第五步:
saveNonConfig();
return fms;
}
這里先來看看FragmentState的源碼
//FragmentState.java
final class FragmentState implements Parcelable {
final String mClassName;
final int mIndex;
final boolean mFromLayout;
final int mFragmentId;
final int mContainerId;
final String mTag;
final boolean mRetainInstance;
final boolean mDetached;
final Bundle mArguments;
final boolean mHidden;
Bundle mSavedFragmentState;
Fragment mInstance;
FragmentState(Fragment frag) {
mClassName = frag.getClass().getName();
mIndex = frag.mIndex;
mFromLayout = frag.mFromLayout;
mFragmentId = frag.mFragmentId;
mContainerId = frag.mContainerId;
mTag = frag.mTag;
mRetainInstance = frag.mRetainInstance;
mDetached = frag.mDetached;
mArguments = frag.mArguments;
mHidden = frag.mHidden;
}
FragmentState(Parcel in) {
mClassName = in.readString();
mIndex = in.readInt();
mFromLayout = in.readInt() != 0;
mFragmentId = in.readInt();
mContainerId = in.readInt();
mTag = in.readString();
mRetainInstance = in.readInt() != 0;
mDetached = in.readInt() != 0;
mArguments = in.readBundle();
mHidden = in.readInt() != 0;
mSavedFragmentState = in.readBundle();
}
public Fragment instantiate(FragmentHostCallback host, FragmentContainer container,
Fragment parent, FragmentManagerNonConfig childNonConfig) {
if (mInstance == null) {
final Context context = host.getContext();
if (mArguments != null) {
mArguments.setClassLoader(context.getClassLoader());
}
if (container != null) {
mInstance = container.instantiate(context, mClassName, mArguments);
} else {
mInstance = Fragment.instantiate(context, mClassName, mArguments);
}
if (mSavedFragmentState != null) {
mSavedFragmentState.setClassLoader(context.getClassLoader());
mInstance.mSavedFragmentState = mSavedFragmentState;
}
mInstance.setIndex(mIndex, parent);
mInstance.mFromLayout = mFromLayout;
mInstance.mRestored = true;
mInstance.mFragmentId = mFragmentId;
mInstance.mContainerId = mContainerId;
mInstance.mTag = mTag;
mInstance.mRetainInstance = mRetainInstance;
mInstance.mDetached = mDetached;
mInstance.mHidden = mHidden;
mInstance.mFragmentManager = host.mFragmentManager;
if (FragmentManagerImpl.DEBUG) {
Log.v(FragmentManagerImpl.TAG, "Instantiated fragment " + mInstance);
}
}
mInstance.mChildNonConfig = childNonConfig;
return mInstance;
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(mClassName);
dest.writeInt(mIndex);
dest.writeInt(mFromLayout ? 1 : 0);
dest.writeInt(mFragmentId);
dest.writeInt(mContainerId);
dest.writeString(mTag);
dest.writeInt(mRetainInstance ? 1 : 0);
dest.writeInt(mDetached ? 1 : 0);
dest.writeBundle(mArguments);
dest.writeInt(mHidden ? 1 : 0);
dest.writeBundle(mSavedFragmentState);
}
public static final @android.annotation.NonNull Parcelable.Creator<FragmentState> CREATOR =
new Parcelable.Creator<FragmentState>() {
@Override
public FragmentState createFromParcel(Parcel in) {
return new FragmentState(in);
}
@Override
public FragmentState[] newArray(int size) {
return new FragmentState[size];
}
};
}
第一步:保存View
//FragmentManager.java
Bundle saveFragmentBasicState(Fragment f) {
Bundle result = null;
if (mStateBundle == null) {
mStateBundle = new Bundle();
}
f.performSaveInstanceState(mStateBundle);
dispatchOnFragmentSaveInstanceState(f, mStateBundle, false);
if (!mStateBundle.isEmpty()) {
result = mStateBundle;
mStateBundle = null;
}
if (f.mView != null) {
//保存Fragment的狀態(tài)
saveFragmentViewState(f);
}
if (f.mSavedViewState != null) {
if (result == null) {
result = new Bundle();
}
result.putSparseParcelableArray(
FragmentManagerImpl.VIEW_STATE_TAG, f.mSavedViewState);
}
if (!f.mUserVisibleHint) {
if (result == null) {
result = new Bundle();
}
// Only add this if it's not the default value
result.putBoolean(FragmentManagerImpl.USER_VISIBLE_HINT_TAG, f.mUserVisibleHint);
}
return result;
}
void saveFragmentViewState(Fragment f) {
if (f.mView == null) {
return;
}
if (mStateArray == null) {
mStateArray = new SparseArray<Parcelable>();
} else {
mStateArray.clear();
}
//這里會調(diào)用view的saveHierarchyState()
f.mView.saveHierarchyState(mStateArray);
if (mStateArray.size() > 0) {
f.mSavedViewState = mStateArray;
mStateArray = null;
}
}
//View.java
public void saveHierarchyState(SparseArray<Parcelable> container) {
dispatchSaveInstanceState(container);
}
//保存當(dāng)前view的狀態(tài)和他的子view,這里就是保存的Fragment及其內(nèi)部的視圖
protected void dispatchSaveInstanceState(SparseArray<Parcelable> container) {
if (mID != NO_ID && (mViewFlags & SAVE_DISABLED_MASK) == 0) {
mPrivateFlags &= ~PFLAG_SAVE_STATE_CALLED;
Parcelable state = onSaveInstanceState();
if ((mPrivateFlags & PFLAG_SAVE_STATE_CALLED) == 0) {
throw new IllegalStateException(
"Derived class did not call super.onSaveInstanceState()");
}
if (state != null) {
// Log.i("View", "Freezing #" + Integer.toHexString(mID)
// + ": " + state);
container.put(mID, state);
}
}
}
第二步:保存Fragment的索引
//FragmentManager.java
public void putFragment(Bundle bundle, String key, Fragment fragment) {
if (fragment.mIndex < 0) {
throwException(new IllegalStateException("Fragment " + fragment
+ " is not currently in the FragmentManager"));
}
bundle.putInt(key, fragment.mIndex);
}
第三步:保存Fragment到數(shù)組中
此部分的源碼就不在這里重復(fù)了,在FragmentManager.java的saveAllState()方法中宪巨。
第四步:保存回退棧
//BackStackRecord.java
final class BackStackState implements Parcelable {
final int[] mOps;
final int mTransition;
final int mTransitionStyle;
final String mName;
final int mIndex;
final int mBreadCrumbTitleRes;
final CharSequence mBreadCrumbTitleText;
final int mBreadCrumbShortTitleRes;
final CharSequence mBreadCrumbShortTitleText;
final ArrayList<String> mSharedElementSourceNames;
final ArrayList<String> mSharedElementTargetNames;
final boolean mReorderingAllowed;
public BackStackState(FragmentManagerImpl fm, BackStackRecord bse) {
final int numOps = bse.mOps.size();
mOps = new int[numOps * 6];
if (!bse.mAddToBackStack) {
throw new IllegalStateException("Not on back stack");
}
int pos = 0;
for (int opNum = 0; opNum < numOps; opNum++) {
final BackStackRecord.Op op = bse.mOps.get(opNum);
mOps[pos++] = op.cmd;
mOps[pos++] = op.fragment != null ? op.fragment.mIndex : -1;
mOps[pos++] = op.enterAnim;
mOps[pos++] = op.exitAnim;
mOps[pos++] = op.popEnterAnim;
mOps[pos++] = op.popExitAnim;
}
mTransition = bse.mTransition;
mTransitionStyle = bse.mTransitionStyle;
mName = bse.mName;
mIndex = bse.mIndex;
mBreadCrumbTitleRes = bse.mBreadCrumbTitleRes;
mBreadCrumbTitleText = bse.mBreadCrumbTitleText;
mBreadCrumbShortTitleRes = bse.mBreadCrumbShortTitleRes;
mBreadCrumbShortTitleText = bse.mBreadCrumbShortTitleText;
mSharedElementSourceNames = bse.mSharedElementSourceNames;
mSharedElementTargetNames = bse.mSharedElementTargetNames;
mReorderingAllowed = bse.mReorderingAllowed;
}
public BackStackState(Parcel in) {
mOps = in.createIntArray();
mTransition = in.readInt();
mTransitionStyle = in.readInt();
mName = in.readString();
mIndex = in.readInt();
mBreadCrumbTitleRes = in.readInt();
mBreadCrumbTitleText = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in);
mBreadCrumbShortTitleRes = in.readInt();
mBreadCrumbShortTitleText = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in);
mSharedElementSourceNames = in.createStringArrayList();
mSharedElementTargetNames = in.createStringArrayList();
mReorderingAllowed = in.readInt() != 0;
}
public BackStackRecord instantiate(FragmentManagerImpl fm) {
BackStackRecord bse = new BackStackRecord(fm);
int pos = 0;
int num = 0;
while (pos < mOps.length) {
BackStackRecord.Op op = new BackStackRecord.Op();
op.cmd = mOps[pos++];
if (FragmentManagerImpl.DEBUG) {
Log.v(FragmentManagerImpl.TAG,
"Instantiate " + bse + " op #" + num + " base fragment #" + mOps[pos]);
}
int findex = mOps[pos++];
if (findex >= 0) {
Fragment f = fm.mActive.get(findex);
op.fragment = f;
} else {
op.fragment = null;
}
op.enterAnim = mOps[pos++];
op.exitAnim = mOps[pos++];
op.popEnterAnim = mOps[pos++];
op.popExitAnim = mOps[pos++];
bse.mEnterAnim = op.enterAnim;
bse.mExitAnim = op.exitAnim;
bse.mPopEnterAnim = op.popEnterAnim;
bse.mPopExitAnim = op.popExitAnim;
bse.addOp(op);
num++;
}
bse.mTransition = mTransition;
bse.mTransitionStyle = mTransitionStyle;
bse.mName = mName;
bse.mIndex = mIndex;
bse.mAddToBackStack = true;
bse.mBreadCrumbTitleRes = mBreadCrumbTitleRes;
bse.mBreadCrumbTitleText = mBreadCrumbTitleText;
bse.mBreadCrumbShortTitleRes = mBreadCrumbShortTitleRes;
bse.mBreadCrumbShortTitleText = mBreadCrumbShortTitleText;
bse.mSharedElementSourceNames = mSharedElementSourceNames;
bse.mSharedElementTargetNames = mSharedElementTargetNames;
bse.mReorderingAllowed = mReorderingAllowed;
bse.bumpBackStackNesting(1);
return bse;
}
public int describeContents() {
return 0;
}
public void writeToParcel(Parcel dest, int flags) {
dest.writeIntArray(mOps);
dest.writeInt(mTransition);
dest.writeInt(mTransitionStyle);
dest.writeString(mName);
dest.writeInt(mIndex);
dest.writeInt(mBreadCrumbTitleRes);
TextUtils.writeToParcel(mBreadCrumbTitleText, dest, 0);
dest.writeInt(mBreadCrumbShortTitleRes);
TextUtils.writeToParcel(mBreadCrumbShortTitleText, dest, 0);
dest.writeStringList(mSharedElementSourceNames);
dest.writeStringList(mSharedElementTargetNames);
dest.writeInt(mReorderingAllowed ? 1 : 0);
}
public static final @android.annotation.NonNull Parcelable.Creator<BackStackState> CREATOR
= new Parcelable.Creator<BackStackState>() {
public BackStackState createFromParcel(Parcel in) {
return new BackStackState(in);
}
public BackStackState[] newArray(int size) {
return new BackStackState[size];
}
};
}
第五步:將回退棧和Fragment數(shù)組保存到FragmentManagerState中
//FragmentManager.java
final class FragmentManagerState implements Parcelable {
FragmentState[] mActive;
int[] mAdded;
BackStackState[] mBackStack;
int mPrimaryNavActiveIndex = -1;
int mNextFragmentIndex;
public FragmentManagerState() {
}
public FragmentManagerState(Parcel in) {
mActive = in.createTypedArray(FragmentState.CREATOR);
mAdded = in.createIntArray();
mBackStack = in.createTypedArray(BackStackState.CREATOR);
mPrimaryNavActiveIndex = in.readInt();
mNextFragmentIndex = in.readInt();
}
public int describeContents() {
return 0;
}
public void writeToParcel(Parcel dest, int flags) {
dest.writeTypedArray(mActive, flags);
dest.writeIntArray(mAdded);
dest.writeTypedArray(mBackStack, flags);
dest.writeInt(mPrimaryNavActiveIndex);
dest.writeInt(mNextFragmentIndex);
}
public static final @android.annotation.NonNull Parcelable.Creator<FragmentManagerState> CREATOR
= new Parcelable.Creator<FragmentManagerState>() {
public FragmentManagerState createFromParcel(Parcel in) {
return new FragmentManagerState(in);
}
public FragmentManagerState[] newArray(int size) {
return new FragmentManagerState[size];
}
};
}
第六步:保存非配置信息
//FragmentManager.java
void saveNonConfig() {
ArrayList<Fragment> fragments = null;
ArrayList<FragmentManagerNonConfig> childFragments = null;
if (mActive != null) {
for (int i=0; i<mActive.size(); i++) {
Fragment f = mActive.valueAt(i);
if (f != null) {
if (f.mRetainInstance) {
if (fragments == null) {
fragments = new ArrayList<>();
}
fragments.add(f);
f.mTargetIndex = f.mTarget != null ? f.mTarget.mIndex : -1;
if (DEBUG) Log.v(TAG, "retainNonConfig: keeping retained " + f);
}
FragmentManagerNonConfig child;
if (f.mChildFragmentManager != null) {
f.mChildFragmentManager.saveNonConfig();
child = f.mChildFragmentManager.mSavedNonConfig;
} else {
// f.mChildNonConfig may be not null, when the parent fragment is
// in the backstack.
child = f.mChildNonConfig;
}
if (childFragments == null && child != null) {
childFragments = new ArrayList<>(mActive.size());
for (int j = 0; j < i; j++) {
childFragments.add(null);
}
}
if (childFragments != null) {
childFragments.add(child);
}
}
}
}
if (fragments == null && childFragments == null) {
mSavedNonConfig = null;
} else {
mSavedNonConfig = new FragmentManagerNonConfig(fragments, childFragments);
}
}
2)恢復(fù)
熟悉了Fragment的流程筐赔,那么接下來看看Fragment的恢復(fù)流程又如何呢?
在Activity的onCreate()中會先檢查是否有需要恢復(fù)的非配置信息揖铜,然后解析保存的view樹,實(shí)例化Fragment 达皿,重新建立回退棧等一系列操作完成后天吓,調(diào)用Fragment的dispatchCreate();就會進(jìn)入到Fragment的生命周期流程中了。
//Activity.java
protected void onCreate(@Nullable Bundle savedInstanceState) {
if (DEBUG_LIFECYCLE) Slog.v(TAG, "onCreate " + this + ": " + savedInstanceState);
if (mLastNonConfigurationInstances != null) {
//第一步:恢復(fù)非配置信息
mFragments.restoreLoaderNonConfig(mLastNonConfigurationInstances.loaders);
}
if (mActivityInfo.parentActivityName != null) {
if (mActionBar == null) {
mEnableDefaultActionBarUp = true;
} else {
mActionBar.setDefaultDisplayHomeAsUpEnabled(true);
}
}
if (savedInstanceState != null) {
mAutoFillResetNeeded = savedInstanceState.getBoolean(AUTOFILL_RESET_NEEDED, false);
mLastAutofillId = savedInstanceState.getInt(LAST_AUTOFILL_ID,
View.LAST_APP_AUTOFILL_ID);
if (mAutoFillResetNeeded) {
getAutofillManager().onCreate(savedInstanceState);
}
Parcelable p = savedInstanceState.getParcelable(FRAGMENTS_TAG);
//第二步:恢復(fù)Fragment的所有信息
mFragments.restoreAllState(p, mLastNonConfigurationInstances != null
? mLastNonConfigurationInstances.fragments : null);
}
mFragments.dispatchCreate();
dispatchActivityCreated(savedInstanceState);
if (mVoiceInteractor != null) {
mVoiceInteractor.attachActivity(this);
}
mRestoredFromBundle = savedInstanceState != null;
mCalled = true;
}
//FragmentController.java
public void restoreAllState(Parcelable state, FragmentManagerNonConfig nonConfig) {
mHost.mFragmentManager.restoreAllState(state, nonConfig);
}
//FragmentManager.java
void restoreAllState(Parcelable state, FragmentManagerNonConfig nonConfig) {
// If there is no saved state at all, then there can not be
// any nonConfig fragments either, so that is that.
if (state == null) return;
FragmentManagerState fms = (FragmentManagerState)state;
if (fms.mActive == null) return;
List<FragmentManagerNonConfig> childNonConfigs = null;
// First re-attach any non-config instances we are retaining back
// to their saved state, so we don't try to instantiate them again.
if (nonConfig != null) {
//反序列化非配置信息
List<Fragment> nonConfigFragments = nonConfig.getFragments();
childNonConfigs = nonConfig.getChildNonConfigs();
final int count = nonConfigFragments != null ? nonConfigFragments.size() : 0;
for (int i = 0; i < count; i++) {
Fragment f = nonConfigFragments.get(i);
if (DEBUG) Log.v(TAG, "restoreAllState: re-attaching retained " + f);
int index = 0; // index of f in fms.mActive
while (index < fms.mActive.length && fms.mActive[index].mIndex != f.mIndex) {
index++;
}
if (index == fms.mActive.length) {
throwException(new IllegalStateException("Could not find active fragment "
+ "with index " + f.mIndex));
}
FragmentState fs = fms.mActive[index];
fs.mInstance = f;
f.mSavedViewState = null;
f.mBackStackNesting = 0;
f.mInLayout = false;
f.mAdded = false;
f.mTarget = null;
if (fs.mSavedFragmentState != null) {
fs.mSavedFragmentState.setClassLoader(mHost.getContext().getClassLoader());
f.mSavedViewState = fs.mSavedFragmentState.getSparseParcelableArray(
FragmentManagerImpl.VIEW_STATE_TAG);
f.mSavedFragmentState = fs.mSavedFragmentState;
}
}
}
// Build the full list of active fragments, instantiating them from
// their saved state.
mActive = new SparseArray<>(fms.mActive.length);
for (int i=0; i<fms.mActive.length; i++) {
FragmentState fs = fms.mActive[i];
if (fs != null) {
FragmentManagerNonConfig childNonConfig = null;
if (childNonConfigs != null && i < childNonConfigs.size()) {
childNonConfig = childNonConfigs.get(i);
}
//這里開始實(shí)例化Fragment
Fragment f = fs.instantiate(mHost, mContainer, mParent, childNonConfig);
if (DEBUG) Log.v(TAG, "restoreAllState: active #" + i + ": " + f);
mActive.put(f.mIndex, f);
// Now that the fragment is instantiated (or came from being
// retained above), clear mInstance in case we end up re-restoring
// from this FragmentState again.
fs.mInstance = null;
}
}
// Update the target of all retained fragments.
if (nonConfig != null) {
List<Fragment> nonConfigFragments = nonConfig.getFragments();
final int count = nonConfigFragments != null ? nonConfigFragments.size() : 0;
for (int i = 0; i < count; i++) {
Fragment f = nonConfigFragments.get(i);
if (f.mTargetIndex >= 0) {
f.mTarget = mActive.get(f.mTargetIndex);
if (f.mTarget == null) {
Log.w(TAG, "Re-attaching retained fragment " + f
+ " target no longer exists: " + f.mTargetIndex);
f.mTarget = null;
}
}
}
}
// Build the list of currently added fragments.
mAdded.clear();
if (fms.mAdded != null) {
for (int i=0; i<fms.mAdded.length; i++) {
Fragment f = mActive.get(fms.mAdded[i]);
if (f == null) {
throwException(new IllegalStateException(
"No instantiated fragment for index #" + fms.mAdded[i]));
}
f.mAdded = true;
if (DEBUG) Log.v(TAG, "restoreAllState: added #" + i + ": " + f);
if (mAdded.contains(f)) {
throw new IllegalStateException("Already added!");
}
synchronized (mAdded) {
mAdded.add(f);
}
}
}
// Build the back stack.
if (fms.mBackStack != null) {
mBackStack = new ArrayList<BackStackRecord>(fms.mBackStack.length);
for (int i=0; i<fms.mBackStack.length; i++) {
BackStackRecord bse = fms.mBackStack[i].instantiate(this);
if (DEBUG) {
Log.v(TAG, "restoreAllState: back stack #" + i
+ " (index " + bse.mIndex + "): " + bse);
LogWriter logw = new LogWriter(Log.VERBOSE, TAG);
PrintWriter pw = new FastPrintWriter(logw, false, 1024);
bse.dump(" ", pw, false);
pw.flush();
}
mBackStack.add(bse);
if (bse.mIndex >= 0) {
setBackStackIndex(bse.mIndex, bse);
}
}
} else {
mBackStack = null;
}
if (fms.mPrimaryNavActiveIndex >= 0) {
mPrimaryNav = mActive.get(fms.mPrimaryNavActiveIndex);
}
mNextFragmentIndex = fms.mNextFragmentIndex;
}
實(shí)例化Fragment
//FragmentState.java
public Fragment instantiate(FragmentHostCallback host, FragmentContainer container,
Fragment parent, FragmentManagerNonConfig childNonConfig) {
if (mInstance == null) {
final Context context = host.getContext();
if (mArguments != null) {
mArguments.setClassLoader(context.getClassLoader());
}
if (container != null) {
mInstance = container.instantiate(context, mClassName, mArguments);
} else {
mInstance = Fragment.instantiate(context, mClassName, mArguments);
}
if (mSavedFragmentState != null) {
mSavedFragmentState.setClassLoader(context.getClassLoader());
mInstance.mSavedFragmentState = mSavedFragmentState;
}
mInstance.setIndex(mIndex, parent);
mInstance.mFromLayout = mFromLayout;
mInstance.mRestored = true;
mInstance.mFragmentId = mFragmentId;
mInstance.mContainerId = mContainerId;
mInstance.mTag = mTag;
mInstance.mRetainInstance = mRetainInstance;
mInstance.mDetached = mDetached;
mInstance.mHidden = mHidden;
mInstance.mFragmentManager = host.mFragmentManager;
if (FragmentManagerImpl.DEBUG) {
Log.v(FragmentManagerImpl.TAG, "Instantiated fragment " + mInstance);
}
}
mInstance.mChildNonConfig = childNonConfig;
return mInstance;
}
四峦椰、擴(kuò)展:
1龄寞、DialogFragment
顯示浮動對話框。使用他創(chuàng)建的對話框有效的替代使用Activity類中的對話框輔助方法汤功∥镆兀可以將片斷對話框內(nèi)如由Activity管理的片斷返回棧,從而使用用戶能夠返回清楚地片斷。
使用步驟:
1.1 自定義DialogFragment的子類
class CustomDialogFragment:DialogFragment() {
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
return inflater.inflate(R.layout.custom_dialogfragment_layout,container,false)
}
}
1.2 顯示對話框
var customDialogFragment = CustomDialogFragment()
customDialogFragment.show(this.supportFragmentManager, "CustomDialogFragment")
1.3 隱藏對話框
customDialogFragment.dismiss()
DialogFragment的使用可以和Fragment的使用一樣色解,這樣我們可以對對話框進(jìn)行抽象封裝茂嗓,包括對對話框的統(tǒng)一管理等。
2科阎、ListFragment
內(nèi)部自帶了一個ListView述吸,將該ListView設(shè)置ID為list ,這個ListFragment如果遇到那種比較單一的菜單導(dǎo)航的時候起來非常方便,如果根據(jù)業(yè)務(wù)需要展示的item的樣式多樣化的話锣笨,個人建議還是用recycleview會更加方便(也許是個人習(xí)慣吧)蝌矛。
來看看簡單使用:
public class CustomListFragment extends ListFragment {
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
List<String> data = new ArrayList<String>();
for (int i = 0; i < 100; i++) {
data.add("leon----" + i);
}
ArrayAdapter<String> adapter = new ArrayAdapter<>(getActivity(), android.R.layout.simple_list_item_1, data);
setListAdapter(adapter);
}
}
ListFragment的源碼就少貼出來一部分,細(xì)節(jié)部分就自己研究吧错英。
public class ListFragment extends Fragment {
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
final Context context = requireContext();
FrameLayout root = new FrameLayout(context);
// ------------------------------------------------------------------
LinearLayout pframe = new LinearLayout(context);
pframe.setId(INTERNAL_PROGRESS_CONTAINER_ID);
pframe.setOrientation(LinearLayout.VERTICAL);
pframe.setVisibility(View.GONE);
pframe.setGravity(Gravity.CENTER);
ProgressBar progress = new ProgressBar(context, null,
android.R.attr.progressBarStyleLarge);
pframe.addView(progress, new FrameLayout.LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));
root.addView(pframe, new FrameLayout.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
// ------------------------------------------------------------------
FrameLayout lframe = new FrameLayout(context);
lframe.setId(INTERNAL_LIST_CONTAINER_ID);
TextView tv = new TextView(context);
tv.setId(INTERNAL_EMPTY_ID);
tv.setGravity(Gravity.CENTER);
lframe.addView(tv, new FrameLayout.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
//這里通過代碼的方法添加了一個ListView
ListView lv = new ListView(context);
lv.setId(android.R.id.list);
lv.setDrawSelectorOnTop(false);
lframe.addView(lv, new FrameLayout.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
root.addView(lframe, new FrameLayout.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
// ------------------------------------------------------------------
root.setLayoutParams(new FrameLayout.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
return root;
}
}
總結(jié):
1入撒、Fragment生命周期的狀態(tài)的變化
2暂幼、Fragment事務(wù)處理的流程
3幕随、DialogFragment的使用