在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的操作。