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

相关推荐
Kapaseker1 小时前
一杯美式搞懂 Any、Unit、Nothing
android·kotlin
BoomHe17 小时前
Now in Android 架构模式全面分析
android·android jetpack
Kapaseker1 天前
一杯美式搞定 Kotlin 空安全
android·kotlin
FunnySaltyFish2 天前
什么?Compose 把 GapBuffer 换成了 LinkBuffer?
算法·kotlin·android jetpack
Kapaseker2 天前
Compose 进阶—巧用 GraphicsLayer
android·kotlin
Kapaseker3 天前
实战 Compose 中的 IntrinsicSize
android·kotlin
黄林晴3 天前
告别 Modifier 地狱,Compose 样式系统要变天了
android·android jetpack
A0微声z5 天前
Kotlin Multiplatform (KMP) 中使用 Protobuf
kotlin
alexhilton5 天前
使用FunctionGemma进行设备端函数调用
android·kotlin·android jetpack
lhDream6 天前
Kotlin 开发者必看!JetBrains 开源 LLM 框架 Koog 快速上手指南(含示例)
kotlin