Android Jetpack 之 LiveData
参考文章:
官方文档
“终于懂了“系列:Jetpack AAC完整解析(二)LiveData 完全掌握!
一、简介
官方定义:
LiveData 是一种可观察的数据存储器类。与常规的可观察类不同,LiveData 具有生命周期感知能力,意指它遵循其他应用组件(如 Activity/Fragment)的生命周期。这种感知能力可确保 LiveData 仅更新处于活跃生命周期状态的应用组件观察者。
使用 LiveData 具有以下优势:
- 确保界面符合数据状态
LiveData 遵循观察者模式。当底层数据发生变化时,LiveData 会通知 Observer 对象。您可以整合代码以在这些 Observer 对象中更新界面。这样一来,您无需在每次应用数据发生变化时更新界面,因为观察者会替您完成更新。 - 不会发生内存泄漏
观察者会绑定到 Lifecycle 对象,并在其关联的生命周期遭到销毁后进行自我清理。 - 不会因 Activity 停止而导致崩溃
如果观察者的生命周期处于非活跃状态(如返回栈中的 Activity),则它不会接收任何 LiveData 事件。 - 不再需要手动处理生命周期
界面组件只是观察相关数据,不会停止或恢复观察。LiveData 将自动管理所有这些操作,因为它在观察时可以感知相关的生命周期状态变化。 - 数据始终保持最新状态
如果生命周期变为非活跃状态,它会在再次变为活跃状态时接收最新的数据。例如,曾经在后台的 Activity 会在返回前台后立即接收最新的数据。 - 适当的配置更改
如果由于配置更改(如设备旋转)而重新创建了 Activity 或 Fragment,它会立即接收最新的可用数据。
二、 接入
implementation 'androidx.lifecycle:lifecycle-livedata:2.2.0'
三、基本使用
以下说明使用 ViewModel+LiveData 方式
步骤一:创建LiveData实例
class NameViewModel : ViewModel() {
val currentName: MutableLiveData<String> by lazy {
MutableLiveData<String>()
}
}
注意:请确保用于更新界面的 LiveData 对象存储在 ViewModel 对象中,而不是将其存储在 Activity 或 Fragment 中,原因如下:
1.避免 Activity 和 Fragment 过于庞大。现在,这些界面控制器负责显示数据,但不负责存储数据状态。
2.将 LiveData 实例与特定的 Activity 或 Fragment 实例分离开,并使 LiveData 对象在配置更改后继续存在。(比如Activity重建,还能有数据)
步骤二:创建Observer实例,实现onChanged()方法,用于接收源数据变化并刷新UI.
步骤三:LiveData实例使用observe()方法添加观察者,并传入LifecycleOwner。
步骤四:LiveData实例使用setValue()/postValue()更新源数据 (子线程要postValue())
注意:子线程改变值用postValue,因为在多线程中操作数据是不安全的,而postValue是通过synchronized关键字确保线程安全
MyViewModel viewModel = new ViewModelProvider(this).get(MyViewModel.class);
//步骤三
viewModel.stringLiveData.observe(this, new Observer<String>() {
//步骤二
@Override
public void onChanged(String s) {
Log.e("MainActivity",s+"----");
}
});
textView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
//步骤四
viewModel.stringLiveData.setValue("哈哈哈哈");
}
});
四、 observeForever(Observer)
使用 observeForever(Observer) 方法在没有关联的 LifecycleOwner 对象的情况下注册一个观察者。在这种情况下,观察者会被视为始终处于活跃状态,因此它始终会收到关于修改的通知。您可以通过调用 removeObserver(Observer) 方法来移除这些观察者。
五、 高级用法
- 转换只会在活跃生命周期里面进行
5.1 数据修改 - Transformations.map
- 对存储在 LiveData 对象中的值应用函数,并将结果传播到下游
val userLiveData: LiveData<User> = UserLiveData()
val userName: LiveData<String> = Transformations.map(userLiveData) {
user -> "${user.name} ${user.lastName}"
}
5.2 数据切换 - Transformations.switchMap
- 与 map() 类似,对存储在 LiveData 对象中的值应用函数,并将结果解封和分派到下游。传递给 switchMap() 的函数必须返回 LiveData 对象,如以下示例中所示:。
private fun getUser(id: String): LiveData<User> {
...
}
val userId: LiveData<String> = ...
val user = Transformations.switchMap(userId) { id -> getUser(id) }
六、Fragment中liveData.observe(this)和liveData.observe(viewLifecycleOwner)的区别
liveData.observe(this) {
// livedata 生命周期将与片段(Fragment)的整个生命周期(onCreate()开始、onDestroy()结束)相关联;
}
liveData.observe(viewLifecycleOwner) {
// livedata 生命周期将与片段(Fragment)何时拥有(和失去)其 UI(onCreateView() 开始、onDestroyView()结束)相关联;
}