Jetpack系列——Lifecycle

534 阅读5分钟

解耦是软件开发中常谈的话题,在Android开发中,解耦很多情况下表现为系统组件的生命周期和普通组件(自定义组件、工具等)的之间的解耦,普通组件在使用过程中经常需要依赖系统组件的生命周期。有时候我们不得不在系统组件的生命周期回调函数中,对普通组件进行控制,因为普通组件无法感知系统组件的生命周期。

例如,我们的定位组件,需要在Activity的onCreate()方法中进行初始化,在onResume()方法中进行定位,在onDestroy()方法中进行资源释放等等。

我们希望自定义的组件能够不依赖于系统组件的生命周期的回调方法,同时,当系统组件生命周期发生变化的时候,能够及时收到通知。为此,Google提出了Lifecycle的解决方案,Lifecycle可以帮助开发者创建可以感知生命周期的组件,这样组件便能够在其内部处理逻辑,降低模块间的耦合,也降低了内存泄漏发生的可能。

Lifecycle不只在Activity、Fragment中可以使用,Service和 Application中也可以使用。

示例

还是之前的案例:当用户打开某个页面的时候,获取用户当前的位置,我们一般会这样写:

class LocationActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        initLocationManager()
    }

    override fun onResume() {
        super.onResume()
        startLocation()
    }

    override fun onDestroy() {
        super.onDestroy()
        stopLocation()
    }
}

从上面代码可以看出,我们为了在一个页面中实现位置定位,不得不在Activity的各个生命周期方法中做一个组件的不同操作,因为组件并不能主动感知系统组件的生命周期。

Lifecycle原理

Jetpack为我们提供了两个类:LifecycleOwner(被观察者)和LifecycleObserver(观察者),即通过观察者模式,实现对组件的生命周期的监听。

阅读源码可以知道,在新版SDK中,SupportActivity已经默认实现了LifecycleOwner接口,该接口中只有一个getLifecycle()方法,LifecycleOwner正是通过该方法实现观察者模式的。

这样,我们在需要监听Activity的生命周期的时候,就不再需要做LifecycleOwner相关的操作,只需要实现观察者这部分的代码就可以。LifecycleObserver接口中没有接口方法,无须任何具体实现。

解决方案

1、编写MyLocationObserver类:

class MyLocationObserver(callback: LocationCallback) : LifecycleObserver {

    init {
        initLocationManager()
    }

    @OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
    private fun onResume() {
        startLocation()
    }

    @OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
    private fun onDestroy() {
        stopLocation()
    }

    interface LocationCallback {
        fun onChanged(location: String)
    }
}

定义MyLocationObserver类实现LifecycleObserver接口,由于LifecycleObserver接口没有任何接口方法,所以其内部的方法需要自定义,各方法需要使用@OnLifecycleEvent注解,该注解中需要传入参数Lifecycle.Event.ON_XXX,用来对应各生命周期,这样,该方法就会在系统组件的对应生命周期执行。

class LocationActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        
        lifecycle.addObserver(MyLocationObserver(object : MyLocationObserver.LocationCallback {
            override fun onChanged(location: String) {
                
            }

        }))
    }

}

在Activity中调用getLifecycle()方法,获取Lifecycle对象,执行addObserver()方法,将LifecycleObserver实例出入即可。

是的,就是这么简单,使用Lifecycle可以轻松地解决自定义组件对系统组件的生命周期的依赖问题,使组件可以自己管理其生命周期,降低代码耦合度,提高复用性。

除了Activity之外,新版本SDK中,Fragment也默认实现了LifecycleOwner接口,使用方法同Activity:

public class Fragment implements ComponentCallbacks, OnCreateContextMenuListener, LifecycleOwner, ViewModelStoreOwner {
	···
}

使用LifecycleService解耦Service

拥有生命周期的组件不仅只有Activity和Fragment,还有一个非常重要的组件就是Service。为了让Service也有类似于Activity对Lifecycle的支持的能力,Android提供了LifecycleService类,该类继承自Service,并且实现了LifecycleOwner接口,使用方法与Activity或Fragment类似:

/**
 * A Service that is also a {@link LifecycleOwner}.
 */
public class LifecycleService extends Service implements LifecycleOwner {

}

使用LifecycleService之前,我们需要先添加依赖:

implementation "androidx.lifecycle:lifecycle-extensions:2.2.0"

和在Activity中使用Lifecycle一样,我们首先需要自定义一个LifeObserver类,其中的方法使用@OnLifecycleEvent注解:

class MyServiceObserver : LifecycleObserver {

    @OnLifecycleEvent(Lifecycle.Event.ON_CREATE)
    fun onCreate() {
        println("onCreate")
    }

    @OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
    fun onDestroy() {
        println("onDestroy")
    }

}

之后,自定义Service类继承自LifecycleService:

class MyService : LifecycleService() {

    private var myServiceObserver: MyServiceObserver

    init {
        myServiceObserver = MyServiceObserver()
        lifecycle.addObserver(myServiceObserver)
    }
}

具体详细示例不再描述,从上面的代码可以看出,当Service的生命周期发生变化的时候,不再需要主动对组件进行通知,组件在其内部可以自行管理生命周期所对应的操作,LifecycleService很好地实现了组件和Service的解耦。

使用ProcessLifecycleOwner监听应用程序的生命周期

Android中具有生命周期的系统组件除了Activity、Fragment和Service之外,还有Application。有时我们会有这样的需求:我们需要监听应用程序当前是在前台还是后台,或者监听前后台切换,目前有不少方案可以实现,但都不够优美。Lifecycle提供了叫做ProgressLifecycleOwner的类,方便开发者监听整个应用程序的生命周期。

使用之前依旧要注意依赖:

implementation "androidx.lifecycle:lifecycle-extensions:2.2.0"

定义LifecycleObserver类:

class ApplicationLifecycleObserver : LifecycleObserver {

    /**
     * 应用程序的整个生命周期中只会执行一次
     */
    @OnLifecycleEvent(Lifecycle.Event.ON_CREATE)
    fun onCreate() {
        println("onCreate")
    }

    /**
     * 应用出现在前台调用
     */
    @OnLifecycleEvent(Lifecycle.Event.ON_START)
    fun onStart() {
        println("onStart")
    }

    /**
     * 应用出现在前台调用
     */
    @OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
    fun onResume() {
        println("onResume")
    }

    /**
     * 应用退到后台调用
     */
    @OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
    fun onPause() {
        println("onPause")
    }

    /**
     * 应用退到后台调用
     */
    @OnLifecycleEvent(Lifecycle.Event.ON_STOP)
    fun onStop() {
        println("onStop")
    }

    /**
     * 永远不会被调用
     */
    @OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
    fun onDestroy() {
        println("onDestroy")
    }
}

由于我们要观察的是整个应用程序,所以需要在Application中编写相关代码:

class MyApplication : Application() {

    override fun onCreate() {
        super.onCreate()
        ProcessLifecycleOwner.get().lifecycle.addObserver(ApplicationLifecycleObserver())
    }
}

运行demo后发现:

  • ProcessLifecycleOwner针对整个应用程序的生命周期,与Activity的数量无关;
  • @OnLifecycleEvent(Lifecycle.Event.ON_CREATE)注解的方法,只会被执行一行,而@OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)永远不会执行;
  • 当程序首次开启,或者由后台切换到前台时,会依次执行@OnLifecycleEvent(Lifecycle.Event.ON_START)方法和@OnLifecycleEvent(Lifecycle.Event.ON_RESUME)方法;
  • 当前台切换到后台时,会依次调用@OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)方法和@OnLifecycleEvent(Lifecycle.Event.ON_STOP)方法,但要注意的是,两个方法的执行会有一定的延后,这是因为系统需要为“旋转屏幕,由于配置变化而导致Activity重建”的情况预留一部分时间。

总结

所有的具有生命周期的组件都可以使用Lifecycle,包括Activity、Fragment、Service和Application。Lifecycle组件的核心作用是帮助开发者进行解耦。在自定义组件中使用Lifecycle,便于管理组件的生命周期,降低内存泄漏风险,使得组件使用起来也更加安全。