# remove & detach Fragment 差别public void removeFragment ( Fragment fragment) { if ( DEBUG) Log . v ( TAG, "remove: " + fragment + " nesting=" + fragment. mBackStackNesting) ; final boolean inactive = ! fragment. isInBackStack ( ) ; if ( ! fragment. mDetached || inactive) { synchronized ( mAdded) { mAdded. remove ( fragment) ; } if ( isMenuAvailable ( fragment) ) { mNeedMenuInvalidate = true ; } fragment. mAdded = false ; fragment. mRemoving = true ; } }
public void detachFragment ( Fragment fragment) { if ( DEBUG) Log . v ( TAG, "detach: " + fragment) ; if ( ! fragment. mDetached) { fragment. mDetached = true ; if ( fragment. mAdded) { if ( DEBUG) Log . v ( TAG, "remove from detach: " + fragment) ; synchronized ( mAdded) { mAdded. remove ( fragment) ; } if ( isMenuAvailable ( fragment) ) { mNeedMenuInvalidate = true ; } fragment. mAdded = false ; } } }
都是移出 mAdded 集合,并将 mAdded 置为 false,区别在更新的标记不同 mRemoving & mDetached。在 FragmentManager 同步状态调用时,有对 remove & detach 的状态同步。
* Changes the state of the fragment manager to {@code newState}. If the fragment manager * changes state or {@code always} is {@code true}, any fragments within it have their * states updated as well. * * @param newState The new state for the fragment manager * @param always If {@code true}, all fragments update their state, even * if {@code newState} matches the current fragment manager's state. */ void moveToState ( int newState, boolean always) { if ( mHost == null && newState != Fragment . INITIALIZING) { throw new IllegalStateException ( "No activity" ) ; } if ( ! always && newState == mCurState) { return ; } mCurState = newState; if ( mActive != null ) { final int numAdded = mAdded. size ( ) ; for ( int i = 0 ; i < numAdded; i++ ) { Fragment f = mAdded. get ( i) ; moveFragmentToExpectedState ( f) ; } final int numActive = mActive. size ( ) ; for ( int i = 0 ; i < numActive; i++ ) { Fragment f = mActive. valueAt ( i) ; if ( f != null && ( f. mRemoving || f. mDetached) && ! f. mIsNewlyAdded) { moveFragmentToExpectedState ( f) ; } } startPendingDeferredFragments ( ) ; if ( mNeedMenuInvalidate && mHost != null && mCurState == Fragment . RESUMED) { mHost. onSupportInvalidateOptionsMenu ( ) ; mNeedMenuInvalidate = false ; } } }
* Moves a fragment to its expected final state or the fragment manager's state, depending * on whether the fragment manager's state is raised properly. * * @param f The fragment to change. */ void moveFragmentToExpectedState ( Fragment f) { if ( f == null ) { return ; } if ( ! mActive. containsKey ( f. mWho) ) { if ( DEBUG) { Log . v ( TAG, "Ignoring moving " + f + " to state " + mCurState + "since it is not added to " + this ) ; } return ; } int nextState = mCurState; if ( f. mRemoving) { if ( f. isInBackStack ( ) ) { nextState = Math . min ( nextState, Fragment . CREATED) ; } else { nextState = Math . min ( nextState, Fragment . INITIALIZING) ; } } moveToState ( f, nextState, f. getNextTransition ( ) , f. getNextTransitionStyle ( ) , false ) ; }
对于 Remove 如果 nextState 是 CREATED,Fragment 只会 f.performDestroyView()
,但如果是 INITIALIZING,分两种情况:
不在回退栈,执行 f.performDestroy()
; 在回退栈,执行 f.performDetach()
; 并 makeInactive(f);
对于 detach,nextState 是 CREATED,也即只执行 f.performDestroyView()
@SuppressWarnings ( "ReferenceEquality" ) void moveToState ( Fragment f, int newState, int transit, int transitionStyle, boolean keepActive) { if ( ( ! f. mAdded || f. mDetached) && newState > Fragment . CREATED) { newState = Fragment . CREATED; } }
# add & attach Fragment 区别由于 addFragment 有 activate 调用,fragment 已经在 mActive 映射里,允许状态同步,但 attach 没有 activate 调用,于是状态不同步。
* Moves a fragment to its expected final state or the fragment manager's state, depending * on whether the fragment manager's state is raised properly. * * @param f The fragment to change. */ void moveFragmentToExpectedState ( Fragment f) { if ( f == null ) { return ; } if ( ! mActive. containsKey ( f. mWho) ) { if ( DEBUG) { Log . v ( TAG, "Ignoring moving " + f + " to state " + mCurState + "since it is not added to " + this ) ; } return ; } int nextState = mCurState; if ( f. mRemoving) { if ( f. isInBackStack ( ) ) { nextState = Math . min ( nextState, Fragment . CREATED) ; } else { nextState = Math . min ( nextState, Fragment . INITIALIZING) ; } } moveToState ( f, nextState, f. getNextTransition ( ) , f. getNextTransitionStyle ( ) , false ) ; }
public void addFragment ( Fragment fragment, boolean moveToStateNow) { if ( DEBUG) Log . v ( TAG, "add: " + fragment) ; * * makeActive ( fragment) ; if ( ! fragment. mDetached) { if ( mAdded. contains ( fragment) ) { throw new IllegalStateException ( "Fragment already added: " + fragment) ; } synchronized ( mAdded) { mAdded. add ( fragment) ; } fragment. mAdded = true ; fragment. mRemoving = false ; if ( fragment. mView == null ) { fragment. mHiddenChanged = false ; } if ( isMenuAvailable ( fragment) ) { mNeedMenuInvalidate = true ; } if ( moveToStateNow) { moveToState ( fragment) ; } } }
public void attachFragment ( Fragment fragment) { if ( DEBUG) Log . v ( TAG, "attach: " + fragment) ; if ( fragment. mDetached) { fragment. mDetached = false ; if ( ! fragment. mAdded) { if ( mAdded. contains ( fragment) ) { throw new IllegalStateException ( "Fragment already added: " + fragment) ; } if ( DEBUG) Log . v ( TAG, "add from attach: " + fragment) ; synchronized ( mAdded) { mAdded. add ( fragment) ; } fragment. mAdded = true ; if ( isMenuAvailable ( fragment) ) { mNeedMenuInvalidate = true ; } } } }
# Show 和 hide Fragment 区别首先,更新 mHidden 标记。
* Marks a fragment as hidden to be later animated in with * {@link #completeShowHideFragment(Fragment)}. * * @param fragment The fragment to be shown. */ public void hideFragment ( Fragment fragment) { if ( DEBUG) Log . v ( TAG, "hide: " + fragment) ; if ( ! fragment. mHidden) { fragment. mHidden = true ; fragment. mHiddenChanged = ! fragment. mHiddenChanged; } } * Marks a fragment as shown to be later animated in with * {@link #completeShowHideFragment(Fragment)}. * * @param fragment The fragment to be shown. */ public void showFragment ( Fragment fragment) { if ( DEBUG) Log . v ( TAG, "show: " + fragment) ; if ( fragment. mHidden) { fragment. mHidden = false ; fragment. mHiddenChanged = ! fragment. mHiddenChanged; } }
故事并没有就此结束,看下这个标记如何使用。
首先,hidden 后,Fragment 下的 View 为 Gone,不贡献视图。
androidx. fragment. app. FragmentStateManager #moveToExpectedStateif ( FragmentManager . USE_STATE_MANAGER && mFragment. mHiddenChanged) { if ( mFragment. mView != null && mFragment. mContainer != null ) { 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) ; }
其次,hidden 后,Fragment 不再贡献菜单项
androidx. fragment. app. FragmentManager #dispatchPrepareOptionsMenuboolean dispatchPrepareOptionsMenu ( @NonNull Menu menu) { if ( mCurState < Fragment . CREATED) { return false ; } boolean show = false ; for ( Fragment f : mFragmentStore. getFragments ( ) ) { if ( f != null ) { if ( isParentMenuVisible ( f) && f. performPrepareOptionsMenu ( menu) ) { show = true ; } } } return show; } androidx. fragment. app. Fragment #performPrepareOptionsMenuboolean performPrepareOptionsMenu ( @NonNull Menu menu) { boolean show = false ; if ( ! mHidden) { if ( mHasMenu && mMenuVisible) { show = true ; onPrepareOptionsMenu ( menu) ; } show |= mChildFragmentManager. dispatchPrepareOptionsMenu ( menu) ; } return show; }
显隐切换完成后,androidx.fragment.app.Fragment#onHiddenChanged 会得到通知调用。
androidx. fragment. app. FragmentManager #completeShowHideFragmentandroidx. fragment. app. FragmentStateManager #moveToExpectedState
# FragmentManager 派发生命周期方法public class FragmentActivity extends ComponentActivity { final FragmentController mFragments = FragmentController . createController ( new HostCallbacks ( ) ) ; }
mFragments 负责 Activity 生命周期方法,派发给 FragmentManager,再遍历逐个派发给旗下的 Fragment。
* Perform initialization of all fragments. */ @SuppressWarnings ( "deprecation" ) @Override protected void onCreate ( @Nullable Bundle savedInstanceState) { mFragments. attachHost ( null ) ; if ( savedInstanceState != null ) { Parcelable p = savedInstanceState. getParcelable ( FRAGMENTS_TAG) ; mFragments. restoreSaveState ( p) ; } super . onCreate ( savedInstanceState) ; mFragmentLifecycleRegistry. handleLifecycleEvent ( Lifecycle. Event . ON_CREATE) ; mFragments. dispatchCreate ( ) ; }
* Moves all Fragments managed by the controller's FragmentManager * into the create state. * <p>Call when Fragments should be created. * * @see Fragment#onCreate(Bundle) */ public void dispatchCreate ( ) { mHost. mFragmentManager. dispatchCreate ( ) ; }
dispatchCreate 终导致 FragmentManagerImpl 的当前状态 mCurState
变更。
androidx. fragment. app. FragmentManager #dispatchCreatevoid dispatchCreate ( ) { mStateSaved = false ; mStopped = false ; mNonConfig. setIsStateSaved ( false ) ; dispatchStateChange ( Fragment . CREATED) ; } androidx. fragment. app. FragmentManager #dispatchStateChangeprivate void dispatchStateChange ( int nextState) { try { mExecutingActions = true ; mFragmentStore. dispatchStateChange ( nextState) ; moveToState ( nextState, false ) ; if ( USE_STATE_MANAGER) { Set < SpecialEffectsController > controllers = collectAllSpecialEffectsController ( ) ; for ( SpecialEffectsController controller : controllers) { controller. forceCompleteAllOperations ( ) ; } } } finally { mExecutingActions = false ; } execPendingActions ( true ) ; } void dispatchStateChange ( int state) { for ( FragmentStateManager fragmentStateManager : mActive. values ( ) ) { if ( fragmentStateManager != null ) { fragmentStateManager. setFragmentManagerState ( state) ; } } }
androidx. fragment. app. FragmentManager #moveToState ( int , boolean ) * Changes the state of the fragment manager to {@code newState}. If the fragment manager * changes state or {@code always} is {@code true}, any fragments within it have their * states updated as well. * * @param newState The new state for the fragment manager * @param always If {@code true}, all fragments update their state, even * if {@code newState} matches the current fragment manager's state. */ void moveToState ( int newState, boolean always) { if ( mHost == null && newState != Fragment . INITIALIZING) { throw new IllegalStateException ( "No activity" ) ; } if ( ! always && newState == mCurState) { return ; } mCurState = newState; if ( USE_STATE_MANAGER) { mFragmentStore. moveToExpectedState ( ) ; } else { for ( Fragment f : mFragmentStore. getFragments ( ) ) { moveFragmentToExpectedState ( f) ; } 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 ; } }
androidx. fragment. app. FragmentManager #moveFragmentToExpectedStatevoid moveToExpectedState ( ) { for ( Fragment f : mAdded) { FragmentStateManager fragmentStateManager = mActive. get ( f. mWho) ; if ( fragmentStateManager != null ) { fragmentStateManager. moveToExpectedState ( ) ; } } for ( FragmentStateManager fragmentStateManager : mActive. values ( ) ) { if ( fragmentStateManager != null ) { fragmentStateManager. moveToExpectedState ( ) ; Fragment f = fragmentStateManager. getFragment ( ) ; boolean beingRemoved = f. mRemoving && ! f. isInBackStack ( ) ; if ( beingRemoved) { makeInactive ( fragmentStateManager) ; } } } }
注意只有在 mActive 集合的 Fragment 才可以 moveToExpectedState
,attach 阶段的 Fragment 并未进入此集合,add 之后才进入,此后 Fragment 接收生命周期方法派发。
# BackStack * Implementation of {@link FragmentManagerImpl.OpGenerator}. * This operation is added to the list of pending actions during {@link #commit()}, and * will be executed on the UI thread to run this FragmentTransaction. * * @param records Modified to add this BackStackRecord * @param isRecordPop Modified to add a false (this isn't a pop) * @return true always because the records and isRecordPop will always be changed */ @Override public boolean generateOps ( ArrayList < BackStackRecord > records, ArrayList < Boolean > isRecordPop) { if ( FragmentManagerImpl . DEBUG) { Log . v ( TAG, "Run: " + this ) ; } records. add ( this ) ; isRecordPop. add ( false ) ; if ( mAddToBackStack) { mManager. addBackStackState ( this ) ; } return true ; }
void addBackStackState ( BackStackRecord state) { if ( mBackStack == null ) { mBackStack = new ArrayList < BackStackRecord > ( ) ; } mBackStack. add ( state) ; }
把当前 backStackRecord 即事务加入 mBackStack 集合。此处可以猜想:当接收 back 事件时,activity 先派发 back 事件给 FragmentManager,如果 mBackStack 存在元素,则将列表末尾的事务 revert,并移出集合,指针向左偏移一位,并直接返回。如果 FragmentManager 不回应 back event,那么由 Activity 继续回应。我们看下具体实现是否这样。
androidx. activity. ComponentActivity #onBackPressed * Called when the activity has detected the user's press of the back * key. The {@link #getOnBackPressedDispatcher() OnBackPressedDispatcher} will be given a * chance to handle the back button before the default behavior of * {@link android.app.Activity#onBackPressed()} is invoked. * * @see #getOnBackPressedDispatcher() */ @Override @MainThread public void onBackPressed ( ) { mOnBackPressedDispatcher. onBackPressed ( ) ; } private final OnBackPressedDispatcher mOnBackPressedDispatcher = new OnBackPressedDispatcher ( new Runnable ( ) { @Override public void run ( ) { ComponentActivity . super . onBackPressed ( ) ; } } ) ; androidx. activity. OnBackPressedDispatcher #onBackPressed * Trigger a call to the currently added {@link OnBackPressedCallback callbacks} in reverse * order in which they were added. Only if the most recently added callback is not * {@link OnBackPressedCallback#isEnabled() enabled} * will any previously added callback be called. * <p> * It is strongly recommended to call {@link #hasEnabledCallbacks()} prior to calling * this method to determine if there are any enabled callbacks that will be triggered * by this method as calling this method. */ @MainThread public void onBackPressed ( ) { Iterator < OnBackPressedCallback > iterator = mOnBackPressedCallbacks. descendingIterator ( ) ; while ( iterator. hasNext ( ) ) { OnBackPressedCallback callback = iterator. next ( ) ; if ( callback. isEnabled ( ) ) { callback. handleOnBackPressed ( ) ; return ; } } if ( mFallbackOnBackPressed != null ) { mFallbackOnBackPressed. run ( ) ; } }
FragmentManager 如何注册 callback
→androidx.fragment.app.FragmentActivity#init
→androidx.fragment.app.FragmentController#attachHost
→androidx.fragment.app.FragmentManager#attachController
@SuppressWarnings ( "deprecation" ) @SuppressLint ( "SyntheticAccessor" ) 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; if ( mParent != null ) { addFragmentOnAttachListener ( new FragmentOnAttachListener ( ) { @SuppressWarnings ( "deprecation" ) @Override public void onAttachFragment ( @NonNull FragmentManager fragmentManager, @NonNull Fragment fragment) { parent. onAttachFragment ( fragment) ; } } ) ; } else if ( host instanceof FragmentOnAttachListener ) { addFragmentOnAttachListener ( ( FragmentOnAttachListener ) host) ; } if ( mParent != null ) { updateOnBackPressedCallbackEnabled ( ) ; } if ( host instanceof OnBackPressedDispatcherOwner ) { OnBackPressedDispatcherOwner dispatcherOwner = ( ( OnBackPressedDispatcherOwner ) host) ; mOnBackPressedDispatcher = dispatcherOwner. getOnBackPressedDispatcher ( ) ; LifecycleOwner owner = parent != null ? parent : dispatcherOwner; mOnBackPressedDispatcher. addCallback ( owner, mOnBackPressedCallback) ; } }
private final OnBackPressedCallback mOnBackPressedCallback = new OnBackPressedCallback ( false ) { @Override public void handleOnBackPressed ( ) { FragmentManager . this . handleOnBackPressed ( ) ; } } ;
androidx. fragment. app. FragmentManager #handleOnBackPressed@SuppressWarnings ( "WeakerAccess" ) void handleOnBackPressed ( ) { execPendingActions ( true ) ; if ( mOnBackPressedCallback. isEnabled ( ) ) { popBackStackImmediate ( ) ; } else { mOnBackPressedDispatcher. onBackPressed ( ) ; } }
看 fragmentManager.popBackStackImmediate ()
@Override public boolean popBackStackImmediate ( ) { checkStateLoss ( ) ; return popBackStackImmediate ( null , - 1 , 0 ) ; }
* Used by all public popBackStackImmediate methods, this executes pending transactions and * returns true if the pop action did anything, regardless of what other pending * transactions did. * * @return true if the pop operation did anything or false otherwise. */ private boolean popBackStackImmediate ( String name, int id, int flags) { execPendingActions ( ) ; ensureExecReady ( true ) ; if ( mPrimaryNav != null && id < 0 && name == null ) { final FragmentManager childManager = mPrimaryNav. getChildFragmentManager ( ) ; if ( childManager. popBackStackImmediate ( ) ) { return true ; } } boolean executePop = popBackStackState ( mTmpRecords, mTmpIsPop, name, id, flags) ; if ( executePop) { mExecutingActions = true ; try { removeRedundantOperationsAndExecute ( mTmpRecords, mTmpIsPop) ; } finally { cleanupExec ( ) ; } } updateOnBackPressedCallbackEnabled ( ) ; doPendingDeferredStart ( ) ; burpActive ( ) ; return executePop; }
popBackStackState 获取回退事务集合,交由 removeRedundantOperationsAndExecute 执行事务回退。
boolean popBackStackState ( ArrayList < BackStackRecord > records, ArrayList < Boolean > isRecordPop, String name, int id, int flags) { if ( mBackStack == null ) { return false ; } if ( name == null && id < 0 && ( flags & POP_BACK_STACK_INCLUSIVE) == 0 ) { int last = mBackStack. size ( ) - 1 ; if ( last < 0 ) { return false ; } records. add ( mBackStack. remove ( last) ) ; isRecordPop. add ( true ) ; } else { int index = - 1 ; if ( name != null || id >= 0 ) { index = mBackStack. size ( ) - 1 ; while ( index >= 0 ) { BackStackRecord bss = mBackStack. get ( index) ; if ( name != null && name. equals ( bss. getName ( ) ) ) { break ; } if ( id >= 0 && id == bss. mIndex) { break ; } index-- ; } if ( index < 0 ) { return false ; } if ( ( flags& POP_BACK_STACK_INCLUSIVE) != 0 ) { index-- ; while ( index >= 0 ) { BackStackRecord bss = mBackStack. get ( index) ; if ( ( name != null && name. equals ( bss. getName ( ) ) ) || ( id >= 0 && id == bss. mIndex) ) { index-- ; continue ; } break ; } } } if ( index == mBackStack. size ( ) - 1 ) { return false ; } for ( int i = mBackStack. size ( ) - 1 ; i > index; i-- ) { records. add ( mBackStack. remove ( i) ) ; isRecordPop. add ( true ) ; } } return true ; }
事务从 mBackStack 回退栈管理集合移出,并加入 records 用于执行事务,对应的 isRecordPop 元素设置为 true,标记位回退事务,最后执行逆向操作,实现回退。
→androidx.fragment.app.FragmentManagerImpl#removeRedundantOperationsAndExecute
→androidx.fragment.app.FragmentManagerImpl#executeOpsTogether
→androidx.fragment.app.FragmentManager#executeOps
→androidx.fragment.app.BackStackRecord#executePopOps
androidx. fragment. app. FragmentManager #executeOps * Run the operations in the BackStackRecords, either to push or pop. * * @param records The list of records whose operations should be run. * @param isRecordPop The direction that these records are being run. * @param startIndex The index of the first entry in records to run. * @param endIndex One past the index of the final entry in records to run. */ 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 ) ; boolean moveToState = i == ( endIndex - 1 ) ; record . executePopOps ( moveToState) ; } else { record . bumpBackStackNesting ( 1 ) ; record . executeOps ( ) ; } } } androidx. fragment. app. BackStackRecord #executePopOps * Reverses the execution of the operations within this transaction. The Fragment states will * only be modified if reordering is not allowed. * * @param moveToState {@code true} if added fragments should be moved to their final state * in ordered transactions */ 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) ) ; 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 ) ; } }
# BackPressedCallback 注册和反注册注册和反注册有些值得揣摩,它和以往的模式略有不同。一般而言,注册和反注册都是提供一对 API,add & remove 或者 register & unregister。但这里 mOnBackPressedDispatcher 只提供 addCallback,反注册是 mOnBackPressedCallback 自己调用 cancel 方法实现。
# 注册androidx. fragment. app. FragmentManager #attachController@SuppressLint ( "SyntheticAccessor" ) 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; if ( host instanceof OnBackPressedDispatcherOwner ) { OnBackPressedDispatcherOwner dispatcherOwner = ( ( OnBackPressedDispatcherOwner ) host) ; mOnBackPressedDispatcher = dispatcherOwner. getOnBackPressedDispatcher ( ) ; LifecycleOwner owner = parent != null ? parent : dispatcherOwner; mOnBackPressedDispatcher. addCallback ( owner, mOnBackPressedCallback) ; } }
# 反注册void dispatchDestroy ( ) { mDestroyed = true ; execPendingActions ( true ) ; endAnimatingAwayFragments ( ) ; dispatchStateChange ( Fragment . INITIALIZING) ; mHost = null ; mContainer = null ; mParent = null ; if ( mOnBackPressedDispatcher != null ) { mOnBackPressedCallback. remove ( ) ; mOnBackPressedDispatcher = null ; } }
注册实现
androidx. activity. OnBackPressedDispatcher #addCallback ( androidx. lifecycle. LifecycleOwner, androidx. activity. OnBackPressedCallback) * Receive callbacks to a new {@link OnBackPressedCallback} when the given * {@link LifecycleOwner} is at least {@link Lifecycle.State#STARTED started}. * <p> * This will automatically call {@link #addCallback(OnBackPressedCallback)} and * remove the callback as the lifecycle state changes. * As a corollary, if your lifecycle is already at least * {@link Lifecycle.State#STARTED started}, calling this method will result in an immediate * call to {@link #addCallback(OnBackPressedCallback)}. * <p> * When the {@link LifecycleOwner} is {@link Lifecycle.State#DESTROYED destroyed}, it will * automatically be removed from the list of callbacks. The only time you would need to * manually call {@link OnBackPressedCallback#remove()} is if * you'd like to remove the callback prior to destruction of the associated lifecycle. * * <p> * If the Lifecycle is already {@link Lifecycle.State#DESTROYED destroyed} * when this method is called, the callback will not be added. * * @param owner The LifecycleOwner which controls when the callback should be invoked * @param onBackPressedCallback The callback to add * * @see #onBackPressed() */ @SuppressLint ( "LambdaLast" ) @MainThread public void addCallback ( @NonNull LifecycleOwner owner, @NonNull OnBackPressedCallback onBackPressedCallback) { Lifecycle lifecycle = owner. getLifecycle ( ) ; if ( lifecycle. getCurrentState ( ) == Lifecycle. State . DESTROYED) { return ; } onBackPressedCallback. addCancellable ( new LifecycleOnBackPressedCancellable ( lifecycle, onBackPressedCallback) ) ; }
onBackPressedCallback 的注册委托给 LifecycleOnBackPressedCancellable,同时,持有 LifecycleOnBackPressedCancellable 的实例引用,但反注册时,onBackPressedCallback 调用 cancel 方法,通知 LifecycleOnBackPressedCancellable 实例反注册。也就是 A 向 C 注册,其实是委托给 B 实现注册,反注册通过 A 持有 B 的引用,也由 B 负责完成。
private class LifecycleOnBackPressedCancellable implements LifecycleEventObserver , Cancellable { private final Lifecycle mLifecycle; private final OnBackPressedCallback mOnBackPressedCallback; @Nullable private Cancellable mCurrentCancellable; LifecycleOnBackPressedCancellable ( @NonNull Lifecycle lifecycle, @NonNull OnBackPressedCallback onBackPressedCallback) { mLifecycle = lifecycle; mOnBackPressedCallback = onBackPressedCallback; lifecycle. addObserver ( this ) ; } @Override public void onStateChanged ( @NonNull LifecycleOwner source, @NonNull Lifecycle. Event event) { if ( event == Lifecycle. Event . ON_START) { mCurrentCancellable = addCancellableCallback ( mOnBackPressedCallback) ; } else if ( event == Lifecycle. Event . ON_STOP) { if ( mCurrentCancellable != null ) { mCurrentCancellable. cancel ( ) ; } } else if ( event == Lifecycle. Event . ON_DESTROY) { cancel ( ) ; } } @Override public void cancel ( ) { mLifecycle. removeObserver ( this ) ; mOnBackPressedCallback. removeCancellable ( this ) ; if ( mCurrentCancellable != null ) { mCurrentCancellable. cancel ( ) ; mCurrentCancellable = null ; } } } androidx. activity. OnBackPressedDispatcher #addCancellableCallback * Internal implementation of {@link #addCallback(OnBackPressedCallback)} that gives * access to the {@link Cancellable} that specifically removes this callback from * the dispatcher without relying on {@link OnBackPressedCallback#remove()} which * is what external developers should be using. * * @param onBackPressedCallback The callback to add * @return a {@link Cancellable} which can be used to {@link Cancellable#cancel() cancel} * the callback and remove it from the set of OnBackPressedCallbacks. */ @SuppressWarnings ( "WeakerAccess" ) @MainThread @NonNull Cancellable addCancellableCallback ( @NonNull OnBackPressedCallback onBackPressedCallback) { mOnBackPressedCallbacks. add ( onBackPressedCallback) ; OnBackPressedCancellable cancellable = new OnBackPressedCancellable ( onBackPressedCallback) ; onBackPressedCallback. addCancellable ( cancellable) ; return cancellable; } private class OnBackPressedCancellable implements Cancellable { private final OnBackPressedCallback mOnBackPressedCallback; OnBackPressedCancellable ( OnBackPressedCallback onBackPressedCallback) { mOnBackPressedCallback = onBackPressedCallback; } @Override public void cancel ( ) { mOnBackPressedCallbacks. remove ( mOnBackPressedCallback) ; mOnBackPressedCallback. removeCancellable ( this ) ; } }