Jetpack系列(一) -- Lifecycle

前言

选读书籍--《Android Jetpack开发 原理解析与应用实战》------ 著: 黄林晴

这系列主要为是初步学习jetpack开发所写,不仅是加深映像,也希望给自己更多的启发。

这个系列一周会至少发布一篇(工作原因),读者也可以来监督我(可享私信催更)。

本篇时间: 23/09/09

AndroidStudio版本: Giraffe 2022.3.1 JDK:17 开发语言: Kotlin

Gradle版本:

Lifecycle基本使用

在大佬黄林晴的书本中,lifecycle使用初始结构如下(与书籍不同,理解就行):

  • 被观察者MainActivity

  • 观察者为自定义类 MainLifeObserver

  • MainActivityObserver实现LifecycleObserver,给需要客制化的方法添加@OnLifecycleEvent注释

  • 添加如下依赖

    groovy 复制代码
    implementation("androidx.lifecycle:lifecycle-livedata-ktx:2.6.1")

但是在最近的版本Google要求废弃@OnLifecycleEvent的使用,如图

意思是这个注释会使用代码生成或反射,增加工作量,应当避免使用。并且给了两个推荐方法------DefaultLifecycleObserverLifecycleEventObserver

DefaultLifecycleObserver

使用方法,观察者自定义类 MainLifeObserver实现DefaultLifecycleObserver接口,重写你需要观察的Activity的生命周期方法。如下:

kotlin 复制代码
class MainLifeObserver: DefaultLifecycleObserver {
    val TAG = "MainLifeObserver"

    override fun onCreate(owner: LifecycleOwner) {
        super.onCreate(owner)
        Log.d(TAG, "onCreate: ")
    }

    override fun onStop(owner: LifecycleOwner) {
        super.onStop(owner)
        Log.d(TAG, "onStop: ")
    }

LifecycleEventObserver

使用方法,观察者自定义类 MainLifeObserver实现LifecycleEventObserver接口,并重写onStateChanged(LifecycleOwner, Lifecycle.Event)方法。

kotlin 复制代码
class MainLifeObserver: LifecycleEventObserver {
    val TAG = "MainLifeObserver"

    override fun onStateChanged(source: LifecycleOwner, event: Lifecycle.Event) {
        Log.d(TAG, "onStateChanged: event --> $event")
    }
}

Lifecycle.Event对应的就是Activity的生命周期枚举类

kotlin 复制代码
    public enum class Event {
        /**
         * Constant for onCreate event of the [LifecycleOwner].
         */
        ON_CREATE,

        /**
         * Constant for onStart event of the [LifecycleOwner].
         */
        ON_START,

        /**
         * Constant for onResume event of the [LifecycleOwner].
         */
        ON_RESUME,

        /**
         * Constant for onPause event of the [LifecycleOwner].
         */
        ON_PAUSE,

        /**
         * Constant for onStop event of the [LifecycleOwner].
         */
        ON_STOP,

        /**
         * Constant for onDestroy event of the [LifecycleOwner].
         */
        ON_DESTROY,

        /**
         * An [Event] constant that can be used to match all events.
         */
        ON_ANY;
    }

MainActivity

当然这样还不行,因为被观察者还没有绑定上观察者,我们需要在MainActivity中设置一下。

kotlin 复制代码
class MainActivity : Activity(), LifecycleOwner {

    lateinit var binding: ActivityMainBinding

    private val lifecycleRegistry = LifecycleRegistry(this@MainActivity)

    override val lifecycle: Lifecycle
        get() = lifecycleRegistry

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)
        val myLifecycleObserver = MainLifeObserver()
        lifecycle.addObserver(myLifecycleObserver)
    }

}

这个是MainActivity继承于android.app.Activity的时候,我们需要实现LifecycleOwner接口,并重写getLifecycle()方法。这个时候我们就要用到 Lifecycle 的唯一实现类LifecycleRegistry。实例化之后直接给到getLifecycle()。

当然目前大部分情况下,不管是AS生成还是Google建议,Activity都是继承于AppCompatActivity的,而AppCompatActivity继承于ComponentActivity,ComponentActivity已经实现了LifecycleOwner接口方法。我们直接调用lifecycle就可以了。

kotlin 复制代码
class MainActivity : AppCompatActivity(){

    lateinit var binding: ActivityMainBinding

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)
        val myLifecycleObserver = MainLifeObserver()
        lifecycle.addObserver(myLifecycleObserver)
    }

}

Log输出

LifecycleEventObserver为例子

使用lifecycle解决内存泄漏问题

在我们编写代码的过程中,总会依附于Activity来完成一些其它刚需。例如ToastDialog,当然也不至于此。但是我们在使用上述两个工具时,会调用到Activity本身的Context。对内存泄漏有初步了解的话,应该知道Context在强引用(直接调用)的时候就有可能会产生内存泄漏,因为它不会在Activity关闭后回收内存。

那这个时候,我们就可以自定义Toast或者Dialog来实现LifecycleObserver(这里不是指具体类,而是泛指lifecycle的观察者),观察Activity的生命周期,当Activity关闭时,我们就可以同步关闭引用了Context的视图。

kotlin 复制代码
class MainActivity : AppCompatActivity(){

    lateinit var binding: ActivityMainBinding

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)
        val dialog = AutoDialog(this)
      //  val myLifecycleObserver = MainLifeObserver()
        lifecycle.addObserver(dialog)
        binding.show.setOnClickListener {
            dialog.show()
        }
    }

    class AutoDialog(context: Context) : Dialog(context), LifecycleEventObserver{
        private val TAG = "Dialog"
        override fun onStateChanged(source: LifecycleOwner, event: Lifecycle.Event) {
            when (event) {
                Lifecycle.Event.ON_DESTROY ->
                    if (isShowing) {
                        Log.d(TAG, "onStateChanged: ")
                        dismiss()
                    }
                else -> {}
            }
        }

    }

}

我这里选择直接在Activity类里添加了一个内部类,但实际情况并不建议这样使用,或者说是不能这么用。因为不管是mvc,mvp还是mvvm都是致力于减轻Activity的代码和解耦view和model,这样反而是反方向发展。在实际情况中建议另开一个类,包括可以自定义视图,不仅Activity中看着简洁,而且还能对这个Dialog进行复用。

疑问

可能大家会问,你这样子操作不就是在Activity执行Destory的时候手动dismiss Dialog一样的效果吗?

没错,效果是一样的,但是使用lifecycle有他的用意,借用黄林晴大佬的原话:

虽然上面的方法(直接在onDestory中dismiss)可以解决内存泄漏问题,但若弹窗类型很多,则需要在onDestory中编写许多额外的处理逻辑,且容易忘记。

不明觉厉,如果我们在实际使用时,用到的像Dialog这种很多,我们为了不让内存泄漏,会在onDestory中写很多代码,不仅不优雅,而且不优雅。

总结

初步认识Lifecycle的使用,也了解了Android使用Lifecycle的重要性。

关于Lifecycle的原理,例如ComponentActivity里是如何实现的Lifecycle,这些东西就不做细究,感兴趣可以自己编写代码通过AS跳转到对应类里去查看,或者直接查阅相关的书本或文章。

demo地址-github

相关推荐
工程师老罗21 小时前
我用Ai学Android Jetpack Compose之Composable与View的区别与联系
android·android jetpack
工程师老罗21 小时前
我用Ai学Android Jetpack Compose之LinearProgressIndicator
android·android jetpack
yzpyzp2 天前
如果后台的Long类型的数据返回是null,那么Android客户端的数据bean的kotlin的Long类型的字段接受到数据后是null空指针吗?
android·kotlin
xvch2 天前
Kotlin 2.1.0 入门教程(二十五)类型擦除
android·kotlin
l软件定制开发工作室2 天前
Jetpack Architecture系列教程之(一)——Jetpack介绍
android jetpack
有点感觉3 天前
Android级联选择器,下拉菜单
kotlin
zhangphil3 天前
Android Coil3缩略图、默认占位图placeholder、error加载错误显示,Kotlin(1)
android·kotlin
xvch4 天前
Kotlin 2.1.0 入门教程(二十三)泛型、泛型约束、协变、逆变、不变
android·kotlin
xvch5 天前
Kotlin 2.1.0 入门教程(二十四)泛型、泛型约束、绝对非空类型、下划线运算符
android·kotlin
zhangphil6 天前
Android Coil ImageLoader MemoryCache设置Key与复用内存缓存,Kotlin
android·kotlin