JetPack系列一(LifeCycle)

839 阅读4分钟

image.png

LifeCycle是什么?

按照谷歌官方的说法,LifeCycle是其为我们提供的一套可以感知UI界面组件比如Activity或者Fragment生命周期状态的组件,使用LifeCycle可以使我们的ctivity或者Fragment更加专注于UI界面逻辑,从而一定程度上减少部分不相关的逻辑,代码更加简洁。

LifeCycle有什么作用?

众所周知,Activity或者Fragment是有生命周期的,在LifeCycle出现之前一些和生命周期相关的操作需要放到Activity或者Fragment的生命周期方法中执行。时间久了之后界面组件的代码就会变得非常臃肿,不易维护。有了LifeCycle之后情况就变得简单多了,由于LifeCycle可以观察Activity或者Fragment生命周期,所以一些与生命周期相关联的操作就可以放到LifeCycle中执行,而界面可以只关注展示和交互。

引入LifeCycle

现在的AS版本一般都比较高,新建的项目一般会自动携带LifeCycle,只是版本可能不是官方最新的。可以选择使用系统自带的版本,也可以配置一下gradle,使用比较新的版本

def lifecycle_version = "2.5.1"
implementation "androidx.lifecycle:lifecycle-runtime-ktx:$lifecycle_version"

一个DEMO

我们将通过一个倒计时的demo来演示一下LifeCycle的用法,之所以选用倒计时案例是因为倒计时是有明确的从开始到结束的周期过程,页面显示出来之后就启动计时,页面结束或者销毁之后停止计时,这个过程和页面的生命周期有比较强的关联性。先来看一下传统的写法:

传统方式

Adv.kt

class Adv(var listener:AdvListener?) {

    private var countDownTimer:CountDownTimer ?= object : CountDownTimer(10000,1000) {
        override fun onTick(p0: Long) {
            Log.d("timer",(p0/1000).toInt().toString())
            listener?.timing((p0/1000).toInt())
        }

        override fun onFinish() {
            listener?.skip()
        }
    }


    fun start(){
        Log.d("timer","计时开始")
        countDownTimer?.start()
    }

    fun cancel(){
        Log.d("timer","停止计时")
        countDownTimer?.cancel()
        countDownTimer = null
    }

    interface AdvListener{
        fun timing(second:Int)
        fun skip()
    }

}

SplashPage.kt

class SplashPage : AppCompatActivity(),Adv.AdvListener {
    private var adv:Adv?=null
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_splash_page)
        adv = Adv(this)
        adv?.start()
        findViewById<TextView>(R.id.time).setOnClickListener {
            startActivity(intent.setClass(this@SplashPage,MainActivity::class.java))
        }
    }

    override fun timing(second: Int) {
        findViewById<TextView>(R.id.time).text=second.toString()
    }

    override fun skip() {
        startActivity(intent.setClass(this@SplashPage,MainActivity::class.java))
        finish()
    }

    override fun onDestroy() {
        super.onDestroy()
        adv?.cancel()
    }
}

Adv类主要是计时器的操作,通过AdvListener接口回调来实时刷新界面。SplashPage在onCreate和onDestroy两个生命周期方法中启动或者取消计时器。

这样的方式当然也能够达到效果,但是弊端和很明显,就是我们想要在实现计时器跟随页面创建和销毁而自动启动或者结束这类效果的时候必须重写Activity的生命周期方法,将相关操作放到生命周期方法中执行。想象一下,如果这种情况发生的频率比较高,而我们又忘记了在onDestory中执行某个取消方法...

LifeCycle改写

既然传统方式有不够便利的地方,就LifeCycle改写一下,看一下使用LifeCycle前后有什么变化。 改写一下Adv和SplashPage两个类,改动不大。

Adv.kt

class Adv(var listener:AdvListener?):LifecycleObserver {

    //...与之前相同

@OnLifecycleEvent(Lifecycle.Event.ON_CREATE)//新版本已经提示弃用了
    fun start(){
        Log.d("timer","计时开始")
        countDownTimer?.start()
    }
    @OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
    fun cancel(){
        Log.d("timer","停止计时")
        countDownTimer?.cancel()
        countDownTimer = null
    }

    interface AdvListener{
       //...
    }
}

SplashPage.kt

class SplashPage : AppCompatActivity(),Adv.AdvListener {
   
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_splash_page)
//        adv=Adv(this)
//        adv?.start()
        lifecycle.addObserver(Adv(this))
        //...其他相同

    //不用在调用销毁方法了
}

采用LifeCycle实现之后,对比传统方式很明显的变化就是一些生命周期方法不要再调用了,不需要再在界面上显式调用start或者cancel方法了。需要注意的是要在界面中注册LifecycleObserver的实现类。

LifecycleObserver的替代方案

前面有提示,OnLifecycleEvent之类的生命周期注解已经在新版本的LifeCycle中弃用了,至于原因,官方文档的解释是 This annotation required the usage of code generation or reflection, which should be avoided,大体意思是应当尽可能减少使用反射。OnLifecycleEvent弃用之后官方给出了解决方案:实现 DefaultLifecycleObserver或者LifecycleEventObserver接口

实现DefaultLifecycleObserver接口

这种方案的核心就是将Adv从实现LifecycleObserver改为实现DefaultLifecycleObserver,然后重写其onCreate和onDestory方法

class Adv(var listener:AdvListener?):DefaultLifecycleObserver {

   //...


    fun start(){
        Log.d("timer","计时开始")
        countDownTimer?.start()
    }

    fun cancel(){
        Log.d("timer","停止计时")
        countDownTimer?.cancel()
        countDownTimer = null
    }

    //...

    override fun onCreate(owner: LifecycleOwner) {
        start()
    }

    override fun onDestroy(owner: LifecycleOwner) {
        cancel()
    }

}

实现LifecycleEventObserver接口

LifecycleEventObserver是一个单方法接口,继承自LifecycleObserver。使用LifecycleEventObserver需要重写其onStateChanged方法,判断event值来执行不同操作。

override fun onStateChanged(source: LifecycleOwner, event: Lifecycle.Event) {
    when(event){
        Lifecycle.Event.ON_CREATE->{
            start()
        }
        Lifecycle.Event.ON_DESTROY->{
            cancel()
        }
        else -> {

        }
    }
}

总结

这一小节作为Jetpack系列的开篇,介绍了一下LifeCycle的使用方式及LifecycleObserver弃用之后的替代方案,后面还会介绍JetPack的一些其他库,LiveDate、ViewModel等等