赞
踩
添加依赖
dependencies { def lifecycle_version = "2.5.1" // ViewModel implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:$lifecycle_version" // ViewModel utilities for Compose implementation "androidx.lifecycle:lifecycle-viewmodel-compose:$lifecycle_version" // LiveData implementation "androidx.lifecycle:lifecycle-livedata-ktx:$lifecycle_version" // Lifecycles only (without ViewModel or LiveData) implementation "androidx.lifecycle:lifecycle-runtime-ktx:$lifecycle_version" // Saved state module for ViewModel implementation "androidx.lifecycle:lifecycle-viewmodel-savedstate:$lifecycle_version" }
Lifecycle
使用两种主要枚举跟踪其关联组件的生命周期状态:
activity
和 fragment
中的回调事件。
可以将状态看作图中的节点,将事件看作这些节点之间的边。
实现 LifecycleObserver
观察者,有两种方法,一种是实现 LifecycleEventObserver
接口,覆写 onStateChanged()
方法,在该方法中监听不同的生命周期事件:
import android.util.Log import androidx.lifecycle.LifecycleEventObserver import androidx.lifecycle.LifecycleOwner import androidx.lifecycle.Lifecycle.Event class MyLifecycleObserver: LifecycleEventObserver { override fun onStateChanged(source: LifecycleOwner, event: Event) { Log.e(TAG, "onStateChanged 事件来源: ${ source.javaClass.name}") when (event) { Event.ON_CREATE -> { Log.e(TAG, "onStateChanged: ON_CREATE") } Event.ON_START -> { Log.e(TAG, "onStateChanged: ON_START") } Event.ON_RESUME -> { Log.e(TAG, "onStateChanged: ON_RESUME") } Event.ON_PAUSE -> { Log.e(TAG, "onStateChanged: ON_PAUSE") } Event.ON_STOP -> { Log.e(TAG, "onStateChanged: ON_STOP") } Event.ON_DESTROY -> { Log.e(TAG, "onStateChanged: ON_DESTROY") } Event.ON_ANY -> { Log.e(TAG, "onStateChanged: ON_ANY") } else -> { } } } companion object { private val TAG = MyLifecycleObserver::class.java.simpleName } }
另一种方法是实现 DefaultLifecycleObserver
接口,该接口是支持默认方法实现的接口类(java8),然后选择你要监听的生命周期方法进行覆写即可:
import android.util.Log import androidx.lifecycle.DefaultLifecycleObserver import androidx.lifecycle.LifecycleOwner class MyLifecycleObserver2 : DefaultLifecycleObserver { override fun onCreate(owner: LifecycleOwner) { Log.e(TAG, "onCreate: ") } override fun onStart(owner: LifecycleOwner) { Log.e(TAG, "onStart: ") } override fun onResume(owner: LifecycleOwner) { Log.e(TAG, "onResume: ") } override fun onPause(owner: LifecycleOwner) { Log.e(TAG, "onPause: ") } override fun onStop(owner: LifecycleOwner) { Log.e(TAG, "onStop: ") } override fun onDestroy(owner: LifecycleOwner) { Log.e(TAG, "onDestroy: ") } companion object { private val TAG = MyLifecycleObserver2::class.java.simpleName } }
实现 LifecycleObserver
观察者对象之后,通过调用 Lifecycle
类的 addObserver()
方法来添加观察者对象:
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
lifecycle.addObserver(MyLifecycleObserver())
lifecycle.addObserver(MyLifecycleObserver2())
}
}
添加观察者对象通常是在 Activity
或者 Fragment
中进行,因为这二者都是LifecycleOwner
接口实现者,它们天生自带 Lifecycle
实例。
LifecycleOwner
是单一方法接口,表示类具有 Lifecycle
。它具有一种方法(即 getLifecycle()
),该方法必须由类实现。 此接口从各个类(如 Fragment
和 AppCompatActivity
)抽象化 Lifecycle
的所有权,并允许编写与这些类搭配使用的组件。任何自定义应用类均可实现 LifecycleOwner
接口。
实现 DefaultLifecycleObserver
的组件可与实现 LifecycleOwner
的组件完美配合,因为所有者可以提供生命周期,而观察者可以注册以观察生命周期。
对于位置跟踪示例,我们可以让 MyLocationListener
类实现 DefaultLifecycleObserver
,然后在 onCreate()
方法中使用 activity
的 Lifecycle
对其进行初始化。这样,MyLocationListener
类便可以“自给自足”,这意味着,对生命周期状态的变化做出响应的逻辑会在 MyLocationListener
(而不是在 activity
)中进行声明。让各个组件存储自己的逻辑可使 activity
和 fragment
逻辑更易于管理。
internal class MyLocationListener( private val context: Context, private val lifecycle: Lifecycle, private val callback: (Location) -> Unit ): DefaultLifecycleObserver { private var enabled = false override fun onStart(owner: LifecycleOwner) { if (enabled) { // connect } } fun enable() { enabled = true if (lifecycle.currentState.isAtLeast(Lifecycle.State.STARTED)) { // connect if not connected } } override fun onStop(owner: LifecycleOwner) { // disconnect if connected } }
对于此实现,LocationListener 类可以完全感知生命周期。如果我们需要从另一个 activity 或 fragment 使用 LocationListener,只需对其进行初始化。所有设置和拆解操作都由类本身管理。
class MyActivity : AppCompatActivity() { private lateinit var myLocationListener: MyLocationListener override fun onCreate(...) { myLocationListener = MyLocationListener(this, lifecycle) { location -> // update UI } Util.checkUserStatus { result -> if (result) { myLocationListener.enable() } } } }
支持库 26.1.0
及更高版本中的 Fragment
和 Activity
均已实现 LifecycleOwner
接口。
如果你有一个自定义类并希望使其成为 LifecycleOwner
,可以使用 LifecycleRegistry
类,但需要将事件转发到该类,如以下代码示例中所示:
class MyActivity : Activity(), LifecycleOwner { private lateinit var lifecycleRegistry: LifecycleRegistry override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) lifecycleRegistry = LifecycleRegistry(this) lifecycleRegistry.markState(Lifecycle.State.CREATED) } public override fun onStart() { super.onStart() lifecycleRegistry.markState(Lifecycle.State.STARTED) } override fun getLifecycle(): Lifecycle { return lifecycleRegistry } }
请参考我的另一篇博文:【深入理解Kotlin协程】lifecycleScope源码追踪扒皮 ,其中对Lifecycle的源码流程进行了简要分析。
下图是 Lifecycle 实现生命周期监听的概要流程:
简要总结:
Activity
的 getLifecycle
方法返回的是一个 LifecycleRegistry
对象,LifecycleRegistry
类正是Lifecycle
接口的实现者。LifecycleRegistry
通过弱引用持有了LifecycleOwner
的对象,也就是Activity
对象 。Activity
的onCreate()
方法中添加了一个透明的 ReportFragment
来专门处理生命周期。ReportFragment
中, API >= 29
时的处理逻辑是,调用 LifecycleCallbacks.registerIn(activity)
方法, 其内容是:为Activity
注册一个Application.ActivityLifecycleCallbacks
的回调接口实现类,这个Callback
被Actvity
内部保存了起来。在 ATMS 跨进程调用ActivityThread
中的 handleStartActivity
方法时,回调Activity
的performStart()
方法,进而回调其保存的Callback
的回调方法,在其中拿到Activity持有的LifecycleRegistry
对象进行分发处理,最终调用到LifecycleEventObserver
观察者对象的onStateChanged()
接口方法。ReportFragment
中, API < 29
时的处理逻辑是, 在ReportFragment
的生命周期方法里,进行事件分发,进而回调LifecycleEventObserver
的onStateChanged()
接口方法。Fragment
中生命周期的处理流程类似,也是交给LifecycleRegistry
来分发,但是生命周期方法的触发是通过宿主 Activity
实现的。监听 Application 的前后台切换在以前是通过 registerActivityLifecycleCallbacks()
判断当前处于栈顶的 Activity 的状态来判断的,现在Jetpack提供了一个简单的API ProcessLifecycleOwner
来直接注册监听:
class MyApp: Application() { override fun onCreate() { super.onCreate() ProcessLifecycleOwner.get().lifecycle.addObserver(AppObserver()) } class AppObserver : DefaultLifecycleObserver { override fun onCreate(owner: LifecycleOwner) { Analytics.report("MyApp --> onCreate") } override fun onStart(owner: LifecycleOwner) { Analytics.report("MyApp --> onStart") } override fun onResume(owner: LifecycleOwner) { Analytics.report("MyApp --> onResume") } override fun onPause(owner: LifecycleOwner) { Analytics.report("MyApp --> onPause") } override fun onStop(owner: LifecycleOwner) { Analytics.report("MyApp --> onStop") } override fun onDestroy(owner: LifecycleOwner) { Analytics.report("MyApp --> onDestroy") } } object Analytics { fun report(state: String) = Log.e("Analytics", state) } }
这里的Observer是复用了Activity的LifecycleObserver,并没有提供一个专门为Application使用的Observer,不过不影响我们监听Application的前后台切换。
当应用启动时会依次调用:
当应用按Home键返回桌面或者切换到最近应用列表界面时会依次调用:
当从桌面返回到应用时会依次调用:
可以看到只有应用第一次创建时会回调 onCreate
方法,后面应用前后台切换时会在 onPause/onStop
和 onStart/onResume
两组回调方法之间切换,可以根据需要选择对应的回调方法进行监听业务处理。
LiveData 是一种可观察的数据存储器类。与常规的可观察类不同,LiveData 具有生命周期感知能力,意指它遵循其他应用组件(如 activity、fragment 或 service)的生命周期。这种感知能力可确保 LiveData 仅更新处于活跃生命周期状态的应用组件观察者。
如果观察者(由 Observer 类表示)的生命周期处于 STARTED
或 RESUMED
状态,则 LiveData 会认为该观察者处于活跃状态。LiveData 只会将更新通知给活跃的观察者。为观察 LiveData 对象而注册的非活跃观察者不会收到更改通知。 (这一点非常重要,也就是说在页面不可见时,观察者对象中的处理逻辑不会被执行,从而节约宝贵的内存和CPU资源。)
使用 LiveData 具有以下优势:
LiveData 对象通常存储在 ViewModel 对象中,并可通过 getter
方法进行访问,如以下示例中所示:
class MyViewModel : ViewModel() {
private val _currentName: MutableLiveData<String> by lazy {
MutableLiveData<String>("Tom") }
val currentName: LiveData<String> = _currentName
fun updateName(name: String) {
_currentName.value = name // 只能在主线程调用
// _currentName.postValue(name) // 主线程、子线程中都可以调用
}
}
LiveData 没有公开可用的方法来更新存储的数据。MutableLiveData 类公开 setValue(T)
和 postValue(T)
方法来修改存储在 LiveData 对象中的值。通常情况下会在 ViewModel 中使用 MutableLiveData,然后 ViewModel 只会向观察者公开不可变的 LiveData 对象。
setValue(T)
和 postValue(T)
方法的区别:
LiveData 的 postValue()
方法有一定的延时,如果想在 postValue()
之后移除观察者,马上调用移除方法,可能会导致部分观察者收不到前面postValue的数据,此时应该使用LiveData的setValue()
,它是即时的进行分发,在下一行代码进行移除观察者也没问题。
注意:请确保用于更新界面的 LiveData 对象存储在 ViewModel 对象中,而不是将其存储在 activity 或 fragment 中,原因如下:
在大多数情况下,应用组件的 onCreate()
方法是开始观察 LiveData 对象的正确着手点,原因如下:
onResume()
方法进行冗余调用。STARTED
状态,就会从它正在观察的 LiveData 对象接收最新值。只有在设置了要观察的 LiveData 对象时,才会发生这种情况。通常,LiveData 仅在数据发生更改时才发送更新,并且仅发送给活跃观察者。此行为的一种例外情况是,观察者从非活跃状态更改为活跃状态时也会收到更新。此外,如果观察者第二次从非活跃状态更改为活跃状态,则只有在自上次变为活跃状态以来值发生了更改时,它才会收到更新。
以下示例代码说明了如何开始观察 LiveData 对象:
class MyActivity: ComponentActivity() { private val myViewModel: MyViewModel by viewModels() override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.livedata_test) val nameTextView = findViewById<TextView>(R.id.tv_user_name) val updateBtn = findViewById<Button>(R.id.btn_update) myViewModel.currentName.observe(this) { newName -> nameTextView.text = newName } updateBtn.setOnClickListener { myViewModel.updateName("张三") } } }
该示例中演示的是按下按钮调用的 setValue()
方法,但也可以出于各种各样的原因调用 setValue()
或 postValue()
来更新 name,这些原因可能包括响应网络请求或数据库加载完成等等。在所有情况下,调用 setValue()
或 postValue()
都会触发观察者并更新界面。
注意:你必须保证调用 setValue(T)
方法时是从主线程更新 LiveData 对象。如果在子线程中执行代码,可以改用 postValue(T) 方法来更新 LiveData 对象。
LiveData 具有生命周期感知能力,遵循 activity 和 fragment 等实体的生命周期。你可以使用 LiveData 在这些生命周期所有者和生命周期不同的其他对象(例如 ViewModel 对象)之间传递数据。ViewModel 的主要责任是加载和管理与界面相关的数据,因此非常适合作为用于保留 LiveData 对象的备选方法。你可以在 ViewModel 中创建 LiveData 对象,然后使用这些对象向界面层公开状态。
activity 和 fragment 不应保留 LiveData 实例,因为它们的用途是显示数据,而不是保持状态。此外,如果 activity 和 fragment 无需保留数据,还可以简化单元测试的编写。
你可能会想在数据层类中使用 LiveData 对象,但 LiveData 并不适合用于处理异步数据流。如果您需要在应用的其他层中使用数据流,请考虑使用 Kotlin Flow,然后使用 asLiveData()
在 ViewModel 中将 Kotlin Flow 转换成 LiveData。如需详细了解如何搭配使用 Kotlin Flow 与 LiveData,请学习此 Codelab。
如果观察者的生命周期处于 STARTED
或 RESUMED
状态,LiveData 会认为该观察者处于活跃状态。以下示例代码说明了如何扩展 LiveData 类:
class StockLiveData(symbol: String) : LiveData<BigDecimal>() {
private val stockManager = StockManager(symbol)
private
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。