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?太难了

相关推荐
叽哥2 小时前
Kotlin学习第 1 课:Kotlin 入门准备:搭建学习环境与认知基础
android·java·kotlin
风往哪边走3 小时前
创建自定义语音录制View
android·前端
用户2018792831673 小时前
事件分发之“官僚主义”?或“绕圈”的艺术
android
用户2018792831673 小时前
Android事件分发为何喜欢“兜圈子”?不做个“敞亮人”!
android
Kapaseker5 小时前
你一定会喜欢的 Compose 形变动画
android
QuZhengRong5 小时前
【数据库】Navicat 导入 Excel 数据乱码问题的解决方法
android·数据库·excel
zhangphil6 小时前
Android Coil3视频封面抽取封面帧存Disk缓存,Kotlin(2)
android·kotlin
程序员码歌13 小时前
【零代码AI编程实战】AI灯塔导航-总结篇
android·前端·后端
书弋江山14 小时前
flutter 跨平台编码库 protobuf 工具使用
android·flutter
来来走走16 小时前
Flutter开发 webview_flutter的基本使用
android·flutter