使用OnBackPressedDispatcher处理回退事件
2020/7/10 23:09:11
本文主要是介绍使用OnBackPressedDispatcher处理回退事件,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
在单 Activity 多 Fragment 的场景下处理回退按键一直是一件比较恶心的事情。前段时间看 jetpack 在宣传中有提到利用 OnBackPressedDispatcher
处理回退,于是研究了一下。
使用
给 Fragment
声明2个变量
- dispatcher
dispatcher: OnBackPressedDispatcher 复制代码
- callback
callback: OnBackPressedCallback 复制代码
分别赋值:
dispatcher = requireActivity().onBackPressedDispatcher callback = object : OnBackPressedCallback(true) { override fun handleOnBackPressed() { // 拦截回退 // do something... } } 复制代码
添加回调:
dispatcher.addCallback(this, callback) 复制代码
手动触发回退:
callback.isEnabled = false dispatcher.onBackPressed() 复制代码
流程分析
先看 Activity的处理:
public void onBackPressed() { mOnBackPressedDispatcher.onBackPressed(); } 复制代码
dispatcher 是一开始就构造的:
private final OnBackPressedDispatcher mOnBackPressedDispatcher = new OnBackPressedDispatcher(new Runnable() { @Override public void run() { ComponentActivity.super.onBackPressed(); } }); 复制代码
回退的时候走dispatcher
的 onBackPressed
:
Iterator<OnBackPressedCallback> iterator = mOnBackPressedCallbacks.descendingIterator(); while (iterator.hasNext()) { OnBackPressedCallback callback = iterator.next(); if (callback.isEnabled()) { callback.handleOnBackPressed(); return; } } if (mFallbackOnBackPressed != null) { mFallbackOnBackPressed.run(); } 复制代码
这里可以看到会把第一个可以触发的 OnBackPressedCallback
触发。注意这里的iterator是降序拿的,也就是后跳的页面先处理。
如果页面都退出了并且 mFallbackOnBackPressed
不是 null,那么随后在它的 run 方法里面触发 Activity 父类的 onBackPressed
方法。
生命周期相关
在 dispatcher
添加 callback 的时候,需要传入 lifecycleOwner
参数:
public void addCallback(@NonNull LifecycleOwner owner, @NonNull OnBackPressedCallback onBackPressedCallback) { onBackPressedCallback.addCancellable( new LifecycleOnBackPressedCancellable(lifecycle, onBackPressedCallback)); } 复制代码
这里给 onBackPressedCallback
添加了取消的回调 LifecycleOnBackPressedCancellable
:
@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; } } 复制代码
- 当生命周期是在
onStart
的时候:
mOnBackPressedCallbacks.add(onBackPressedCallback); OnBackPressedCancellable cancellable = new OnBackPressedCancellable(onBackPressedCallback); onBackPressedCallback.addCancellable(cancellable); 复制代码
这里把回退的回调添加到分发对象中。
mCurrentCancellable是一个 OnBackPressedCancellable
对象:
public void cancel() { mOnBackPressedCallbacks.remove(mOnBackPressedCallback); mOnBackPressedCallback.removeCancellable(this); } 复制代码
- 当生命周期进入
onStop
的时候:
会调用上面的 cancel
, 移除掉这个 callback
- 当生命周期进入
onDestroy
的时候:
直接调用 LifecycleOnBackPressedCancellable
的 cancel
方法移除回调。
整体的流程图如下:
![image](/upload/202007/10/202007102309110486.png)
总结
使用 OnBackPressedDispatcher
处理回退事件优点:
- API 简单明了
- 自动根据生命周期来绑定和移除回退监听
请关注我的微信公众号 【半行代码】
![](/upload/202007/10/202007102309112498.png)
这篇关于使用OnBackPressedDispatcher处理回退事件的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-01-18android.permission.read_media_video
- 2024-01-18android_getaddrinfo failed eai_nodata
- 2024-01-18androidmo
- 2024-01-15Android下三种离屏渲染技术
- 2024-01-09Android 蓝牙使用
- 2024-01-06Android对接华为AI - 文本识别
- 2023-11-15代码安全之代码混淆及加固(Android)
- 2023-11-10简述Android语音播报TTS
- 2023-11-06Android WiFi工具类
- 2023-07-22Android开发未来的出路