前言
选读书籍–《Android Jetpack开发 原理解析与应用实战》—— 著: 黄林晴
这系列主要为是初步学习jetpack开发所写,不仅是加深映像,也希望给自己更多的启发。
这个系列一周会至少发布一篇(工作原因),读者也可以来监督我(可享私信催更)。
本篇时间: 23/09/09
AndroidStudio
版本: Giraffe 2022.3.1 JDK:17 开发语言: Kotlin
Gradle版本:
Lifecycle基本使用
在大佬黄林晴的书本中,lifecycle使用初始结构如下(与书籍不同,理解就行):
-
被观察者
MainActivity
-
观察者为自定义类
MainLifeObserver
-
在
MainActivityObserver
实现LifecycleObserver,给需要客制化的方法添加@OnLifecycleEvent
注释 -
添加如下依赖
implementation("androidx.lifecycle:lifecycle-livedata-ktx:2.6.1")
但是在最近的版本Google要求废弃@OnLifecycleEvent
的使用,如图
意思是这个注释会使用代码生成或反射,增加工作量,应当避免使用。并且给了两个推荐方法——DefaultLifecycleObserver
和LifecycleEventObserver
。
DefaultLifecycleObserver
使用方法,观察者自定义类 MainLifeObserver
实现DefaultLifecycleObserver
接口,重写你需要观察的Activity的生命周期方法。如下:
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)方法。
class MainLifeObserver: LifecycleEventObserver {
val TAG = "MainLifeObserver"
override fun onStateChanged(source: LifecycleOwner, event: Lifecycle.Event) {
Log.d(TAG, "onStateChanged: event --> $event")
}
}
Lifecycle.Event
对应的就是Activity的生命周期枚举类
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中设置一下。
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就可以了。
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来完成一些其它刚需。例如Toast
,Dialog
,当然也不至于此。但是我们在使用上述两个工具时,会调用到Activity本身的Context。对内存泄漏有初步了解的话,应该知道Context在强引用(直接调用)的时候就有可能会产生内存泄漏,因为它不会在Activity关闭后回收内存。
那这个时候,我们就可以自定义Toast或者Dialog来实现LifecycleObserver(这里不是指具体类,而是泛指lifecycle的观察者),观察Activity的生命周期,当Activity关闭时,我们就可以同步关闭引用了Context的视图。
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跳转到对应类里去查看,或者直接查阅相关的书本或文章。