生命周期感知型组件可执行操作来响应另一个组件(如 Activity 和 Fragment)的生命周期状态的变化。androidx.lifecycle 软件包提供了可用于构建生命周期感知型组件的类和接口,这些组件可以根据 Activity 或 Fragment 的当前生命周期状态自动调整其行为。
Lifecycle
用于存储有关组件(如 Activity 或 Fragment)的生命周期状态的信息,并允许其他对象观察此状态。 Lifecycle 使用两种主要枚举跟踪其关联组件的生命周期状态:
- 事件:从框架和 Lifecycle 类分派的生命周期事件
- 状态:由 Lifecycle 对象跟踪的组件的当前状态

我们可以通过实现 DefaultLifecycleObserver 并替换相应的方法来监控组件的生命周期状态,然后调用 Lifecycle 类的 addObserver 方法并传递观察器的实例来添加观察器。
class MyLifecycleObserver : DefaultLifecycleObserver {
private val tag = "MyLifecycleObserver"
override fun onCreate(owner: LifecycleOwner) {
super.onCreate(owner)
Log.i(tag, "onCreate")
}
override fun onDestroy(owner: LifecycleOwner) {
super.onDestroy(owner)
Log.i(tag, "onDestroy")
}
}
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val binding =
DataBindingUtil.setContentView<ActivityMainBinding>(this, R.layout.activity_main)
lifecycle.addObserver(MyLifecycleObserver())
}
}
LifecycleOwner 是单一方法接口,表示类具有 Lifecycle,实现 DefaultLifecycleObserver 的组件可与实现 LifecycleOwner 的组件完美配合,因为所有者可以提供生命周期,而观察者可以注册以观察生命周期,Fragment 和 Activity 已经实现了 LifecycleOwner 接口。
我们也可以查询当前状态,例如
if (lifecycle.currentState.isAtLeast(Lifecycle.State.STARTED)) {
//todo
}
ViewModel
ViewModel 是一种业务逻辑或屏幕级状态容器,它用于将状态公开给界面,以及封装相关的业务逻辑。 它可以缓存状态,并可在配置更改后持久保留相应状态,这就意味着在 Activity 之间导航时或进行配置更改后(例如旋转屏幕时),界面无需重新提取数据。

ViewModel 的生命周期从 Activity 首次创建(onCreate)开始,直到 Activity 真正销毁(onDestroy)且不再重建时才会销毁。ViewModel 的生命周期与 Activity 的 ViewModelStore 相关联,只要 Activity 的 ViewModelStore 存在,ViewModel 就会存在,屏幕旋转时,Activity 的 ViewModelStore 会被保留,因此 ViewModel 不会被销毁。
LiveData
LiveData 是一种具有生命周期感知能力的可观察的数据存储器类,它遵循其他应用组件(如 activity,fragment 或 service)的生命周期。如果观察者的生命周期处于 STARTED 或 RESUMED 状态,则 LiveData 会认为该观察者处于活跃状态,LiveData 只会将更新通知给活跃的观察者,非活跃观察者不会收到更改通知。
这对于 activity 和 fragment 特别有用,可以放心地观察 LiveData 对象,不必担心泄露,因为当 activity 和 fragment 的生命周期被销毁时,系统会立即退订它们。
这里通过一个简单的示例,来说明 ViewModel 和 LiveData 的使用。
implementation "androidx.activity:activity-ktx:1.5.1"
class MainViewModel : ViewModel() {
val showText = MutableLiveData<String>()
}
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
<data>
<variable
name="showText"
type="String" />
<variable
name="click"
type="com.example.myapplication.MainActivity.ClickEventListener" />
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical"
tools:context=".MainActivity">
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="@{click::changeText}"
android:text="change"
android:textAllCaps="false" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{showText}" />
</LinearLayout>
</layout>
class MainActivity : AppCompatActivity() {
private val mainViewModel by viewModels<MainViewModel>()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val binding =
DataBindingUtil.setContentView<ActivityMainBinding>(this, R.layout.activity_main)
with(binding) {
showText = "Original Content"
click = ClickEventListener()
}
mainViewModel.showText.observe(this) {
binding.showText = it
}
}
inner class ClickEventListener {
fun changeText(view: View) {
mainViewModel.showText.value = "Content After Change"
}
}
}