在Fragment中處理返回鍵操作
在新版的AndroidX之前,我們想要自定義處理返回鍵操作,必須得在activity和fragment中自己實現。
而在新版的AndroidX的Fragment相關組件中,加入了可以自定義處理后退按鈕的操作,
getActivity().getOnBackPressedDispatcher().addCallback(getViewLifecycleOwner(), new OnBackPressedCallback(true) { @Override public void handleOnBackPressed() { xxxx } });
有兩個addCallback:
@MainThread public void addCallback(@NonNull LifecycleOwner owner, @NonNull OnBackPressedCallback onBackPressedCallback) @MainThread public void addCallback(@NonNull OnBackPressedCallback onBackPressedCallback)
區別在於,
- l 有LifecycleOwner的會根據lifecycle自動的添加和刪除callback,
- l 而第二個刪除時需要手動調用OnBackPressedCallback.remove(),
源碼分析
具體就是在ComponentActivity中:
/** * 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(); } /** * Retrieve the {@link OnBackPressedDispatcher} that will be triggered when {@link #onBackPressed()} is called. * @return The {@link OnBackPressedDispatcher} associated with this ComponentActivity. */ @NonNull @Override public final OnBackPressedDispatcher getOnBackPressedDispatcher() { return mOnBackPressedDispatcher; }
OnBackPressedDispatcher.onBackPressed()
/** 觸發對當前添加的OnBackPressedCallback的調用,調用的順序與添加它們的順序相反。 只有最近添加的OnBackPressedCallback未啟用時,才會調用以前添加的回調。 強烈建議在調用此方法之前調用hasEnabledCallbacks(),以確定在調用此方法時此方法是否會觸發任何已啟用的回調。 */ @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(); } }
而mFallbackOnBackPressed是指當沒有OnBackPressedCallback時進行的操作,
在ComponentActivity中創建OnBackPressedDispatcher時傳遞了這個mFallbackOnBackPressed:
private final OnBackPressedDispatcher mOnBackPressedDispatcher = new OnBackPressedDispatcher(new Runnable() { @Override public void run() { ComponentActivity.super.onBackPressed(); } });
也就是調用activity的onBackPressed。
OnBackPressedCallback
public abstract class OnBackPressedCallback { private boolean mEnabled; public OnBackPressedCallback(boolean enabled) { mEnabled = enabled; } /** * Set the enabled state of the callback. Only when this callback * is enabled will it receive callbacks to {@link #handleOnBackPressed()}. * <p> * Note that the enabled state is an additional layer on top of the * {@link androidx.lifecycle.LifecycleOwner} passed to * {@link OnBackPressedDispatcher#addCallback(LifecycleOwner, OnBackPressedCallback)} * which controls when the callback is added and removed to the dispatcher. * * @param enabled whether the callback should be considered enabled */ @MainThread public final void setEnabled(boolean enabled) { mEnabled = enabled; } /** * Checks whether this callback should be considered enabled. Only when this callback * is enabled will it receive callbacks to {@link #handleOnBackPressed()}. * * @return Whether this callback should be considered enabled. */ @MainThread public final boolean isEnabled() { return mEnabled; } /** * Removes this callback from any {@link OnBackPressedDispatcher} it is currently * added to. */ @MainThread public final void remove() { for (Cancellable cancellable: mCancellables) { cancellable.cancel(); } } /** * Callback for handling the {@link OnBackPressedDispatcher#onBackPressed()} event. */ @MainThread public abstract void handleOnBackPressed(); }
OnBackPressedDispatcher
public OnBackPressedDispatcher(@Nullable Runnable fallbackOnBackPressed) { mFallbackOnBackPressed = fallbackOnBackPressed; } @MainThread public void addCallback(@NonNull OnBackPressedCallback onBackPressedCallback) { addCancellableCallback(onBackPressedCallback); } @MainThread @NonNull Cancellable addCancellableCallback(@NonNull OnBackPressedCallback onBackPressedCallback) { mOnBackPressedCallbacks.add(onBackPressedCallback); OnBackPressedCancellable cancellable = new OnBackPressedCancellable(onBackPressedCallback); onBackPressedCallback.addCancellable(cancellable); return cancellable; } @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)); } @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(); } } private class OnBackPressedCancellable implements Cancellable { private final OnBackPressedCallback mOnBackPressedCallback; OnBackPressedCancellable(OnBackPressedCallback onBackPressedCallback) { mOnBackPressedCallback = onBackPressedCallback; } @Override public void cancel() { mOnBackPressedCallbacks.remove(mOnBackPressedCallback); mOnBackPressedCallback.removeCancellable(this); } } 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) { // Should always be non-null 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; } } }
為什么要手動刪除callback時需要調用OnBackPressedCallback.remove()?
因為addCallback里會把OnBackPressedCallback進行一個封裝(OnBackPressedCancellable/LifecycleOnBackPressedCancellable ),然后加入到了OnBackPressedCallback中,
當調用OnBackPressedCallback.remove()時就會去調用封裝的cancel方法,而在cancel中有刪除callback的操作。