ComponentDialog—集各种特性于一体的大成Dialog

大家好,本篇文章给大家分享下官方开源库activity-ktx提供的几个有用的小工具,希望能对你有所帮助,本篇文章为大家带来ComponentDialog的介绍。

当前基于如下版本进行分析:

groovy 复制代码
dependencies {
    implementation "androidx.activity:activity-ktx:1.8.0"
}

ComponentDialog---集各种特性于一体的大成Dialog

如果经常使用Android Jetpack相关组件的开发者,相信对下面的几个接口非常了解:

  • LifecycleOwner:提供组件可观察的生命周期
  • OnBackPressedDispatcherOwner:提供系统返回按钮事件的监听;
  • SavedStateRegistryOwner:保存因配置发生更改界面销毁重建前的相关数据,重建后能够重新获取

借助于官方的支持,上面这些接口特性在ActivityFragment中都有体现,但是大家想一想,Dialog有这个待遇吗?哈哈,这不ComponentDialog组件就应运而生了。

kotlin 复制代码
open class ComponentDialog @JvmOverloads constructor(
    context: Context,
    @StyleRes themeResId: Int = 0
) : Dialog(context, themeResId),
    LifecycleOwner,
    OnBackPressedDispatcherOwner,
    SavedStateRegistryOwner {
        //...
}

ComponentDialog实现了上面的三个接口,所以拥有了三个接口对应的能力,接下来咱们来分别演示下。

先自定义一个ComponentDialog类:

kotlin 复制代码
class CustomComponentDialog(mContext: Context): ComponentDialog(mContext) {

    override fun onSaveInstanceState(): Bundle {
        return super.onSaveInstanceState()
    }
}

1. LifecycleOwner能力

kotlin 复制代码
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val customComponentDialog = CustomComponentDialog(this)
        customComponentDialog.show()
        customComponentDialog.lifecycle.addObserver(object : DefaultLifecycleObserver {
            override fun onCreate(owner: LifecycleOwner) {
                super.onCreate(owner)
            }

            override fun onResume(owner: LifecycleOwner) {
                super.onResume(owner)
            }

            override fun onDestroy(owner: LifecycleOwner) {
                super.onDestroy(owner)
            }
        })
    }

如果是我们直接之前使用Dialog,为了监听Dialog的show和dismiss等场景,都会主动调用方法诸如setOnDismissListenersetOnShowListener等设置监听器,这样就会导致一个安全隐患:Dialog持有了外部类引用,而这个外部类引用会被对象池中的Message持有,如果这个Message和HanderThread消息队列中的Message共享,那这就产生内存泄漏的安全隐患。DialogFragment也同样存在这样的安全隐患。

这个内存泄漏的安全隐患就不再这里进行分析了,大家可以这两篇文章了解学习一番:

Android开发:Message 引发的 DialogFragment 内存泄漏分析与解决方案

使用Dialog可能引起的内存泄漏

而现在ComponentDialog提供了Lifecycle的能力,我们就可以通过添加观察者的方式来监听Dialog的show和dismiss,而不会产生丝毫内存泄漏的安全隐患,大家可以放心食用。

不过这里有两点需要注意的地方:

  1. lifecycle的resume方法执行是早于监听器setOnShowListener(DialogInterface.OnShowListener)回调时机,其借助ComponentDialog#onStart()方法通知观察者Resume事件发生

  2. lifecycle的destory方法执行同样早于监听器setOnDismissListener(DialogInterface#OnDismissListener)回调时机,其借助ComponentDialog#onStop通知观察者onDestory事件产生

2. OnBackPressedDispatcherOwner能力

提供监听系统返回按键点击事件的能力

arduino 复制代码
customComponentDialog.onBackPressedDispatcher.addCallback {
    Log.i("TAG", "onCreate: onBackPressedDispatcher")

    isEnable = false
}

不过这个工具可要善用,比如如果上面代码中没有关键的isEnable = false,那么相当于系统返回按钮事件就被这个Dialog给拦截了,其他的地方back事件都无法响应了

所以当处理完Dialog的back监听事件后,需要主动设置isEnable = false才能保证该系统返回键点击事件能够正常流转,当然了具体要视业务场景而定。

具体的应用场景也会有不少,比如当前正在显示一个提供编辑能力的Dialog,先设置个onBack监听,在点击系统返回键时,提示用户是否要保存草稿等类似功能。相比较直接重写onKeyUp、onBackPress等系统方法,设置onBackPressedCallback的方式使用起来更加灵活方便。

顺便给大家推荐一个好用的扩展方法,这样添加onback监听就十分方便了:

3. SavedStateRegistryOwner能力

这个类似于有点类似于ViewModel,能够保存状态数据,比如当界面由于旋转、换肤等此原因导致Activity重建时,就可以将之前的数据进行重现,和ViewModel的能力有点像。

scss 复制代码
customComponentDialog.savedStateRegistry.registerSavedStateProvider("key") {
    Bundle().apply { 
        putInt("count", 100)
    }
}

指定一个key,以及要存储的数据即可,最终这个伴随着Dialog#onSaveInstanceState()一起存储。

不过这个作用感觉使用场景不大,而且存在使用限制,而且Dialog依赖Activity的context,直接使用Activity的ViewModel保存数据也能实现Dialog状态数据的保存以及恢复。

当然了仁者见仁,智者见智,对于Dialog使用的这个特性再这里就不再提了。

历史文章

一文洞彻:Application为啥不能作为Dialog的context?

这篇文章大家可以看看哈,也是使用Dialog时需要了解的一个知识点,带你了解Dialog的context一定不能是Application吗?只能是Activity吗?

子线程刷UI->Barrier屏障->主线程装死->应用GG?太难了

相关推荐
尚久龙23 分钟前
安卓学习 之 用户登录界面的简单实现
android·运维·服务器·学习·手机·android studio·安卓
Modu_MrLiu27 分钟前
Android实战进阶 - 启动页
android·实战进阶·启动页·倒计时场景
出门吃三碗饭1 小时前
编译器构造:从零手写汇编与反汇编程序(一)
android·汇编
Just_Paranoid2 小时前
【WorkManager】无法在 Direct Boot 模式下初始化
android·jetpack·usermanager·workmanager·directboot
前端小超超2 小时前
如何配置capacitor 打包的安卓app固定竖屏展示?
android·前端·gitee
顾林海2 小时前
探秘Android JVM TI:虚拟机背后的"隐形管家"
android·面试·性能优化
刘大国4 小时前
<android>反编译魔改安卓系统应用并替换
android
恋猫de小郭4 小时前
Flutter Riverpod 3.0 发布,大规模重构下的全新状态管理框架
android·前端·flutter
纤瘦的鲸鱼4 小时前
MySQL慢查询
android·adb
郭庆汝4 小时前
模型部署:(三)安卓端部署Yolov8-v8.2.99目标检测项目全流程记录
android·yolo·目标检测·yolov8