LiveData是Google Jetpack库中提供的一种可观察的数据存储器类,是一种可以与任意数据类型一起使用的包装器。
LiveData可以感知生命周期,观察者(Observer
)处于Started
或Resumed
状态时,LiveData认为该观察者处于活跃状态,会将更新通知给活跃观察者,而已注册非活跃状态的观察者不会收到更新。这样当Activity和Fragment生命周期结束时,便可移除观察者而不必担心泄露。
LiveData特点:
- 在LiveData的观察者对象中进行与数据状态相关的界面更新操作;
- 观察者会绑定Lifecycle对象,当与其关联的生命周期结束时进行自我清理;
- 当activity或fragment由非活跃状态变为活跃状态时,会立即接收最新数据;
- 设备配置更改时(例如屏幕旋转或中英文切换)而创建新activity或fragment时会接收最新数据;
- 可使用单例模式扩展LiveData对象并包装成系统服务,以便在应用程序中共享(事件总线LiveDataBus)。
MutableLiveData和LiveData
- MutableLiveData继承自LiveData;
- LiveData可以通知指定的某字段的数据更新,外部需MutableLiveData类才能改变容器内容;
- MutableLiveData整个实体类或数据类型变化后才通知,不会细节到字段;
- MutableLiveData提供了改变容器内容的接口
setValue/postValue
;
LiveData使用
1、创建LiveData对象
MVVM模式下,一般在ViewModel中声明和保存LiveData,主要目的是:
- Activity和Fragment中只进行UI数据显示,数据状态变更在ViewModel中进行
- LiveData在ViewModel中声明时,生命周期与activity或fragment分离,配置变更后LiveData仍然存活。
2、订阅LiveData对象
官方推荐在onCreate()
方法中开始观察LiveData对象理由是:
- 确保在Activity或Fragment一变为活跃状态就可以接收更新数据
- 确保系统不会在activity或Fragment的
onResume()
方法中进行多余调用
第一种使用LiveData方法
//ViewModel类创建LiveData示例
public class XViewModel extends ViewModel{
MutableLiveData<String> msgData;
public MutableLiveData<String> getMsgData(){
if (msgData == null){
msgData = new MutableLiveData<>();
}
return msgData;
}
public void request(MutableLiveData<String> msgData, Param param){
//请求网络数据,将msgData作为参数传递, 在请求的回调中使用postValue给msgData赋值
}
}
//activity中订阅观察者
viewModel.getMsgData().observe(this, new Observer<String>(){
@override
public void onChanged(String s){
//UI数据操作
} );
第二种使用LiveData方法(Transformations.switchMap)
Transformations.switchMap介绍
- 谷歌为LiveData组件提供的对存储在LiveData中的值进行更改后再分配给观察者的方法;
- LiveData包提供Transformations类支持对LiveData对象内部值的修改;
- Transformations.map()强调的是改变当前LiveData内部数据,返回的结果与传入的LiveData直接相关,例如字符串修改,数据值更改等;
- Transformations.switchMap根据当前LiveData,返回一个LiveData类型的数据,可用来获取网络数据
public class XViewModel extends ViewModel{
//创建对请求参数进行观测的LiveData对象
private MutableLiveData<String> reqData = new MutableLiveData<>();
//创建对请求结果进行观测的LiveData对象
public LiveData<String> msgData = Transformations.switchMap(reqData, this::requestMsgData);
public LiveData<String> requestMsgData(RequestData reqData)
{
//请求网络数据,方法返回值为LiveData<String>类型
}
}
//LiveData直接在activity或fragment中设置观察
//在dealData中处理UI数据
viewModel.msgData.observer(this, this::dealData);
postValue()
postValue的特性如下:
- 此方法可以在其他线程中调用
- 如果在主线程执行发布的任务之前多次调用此方法,则仅将分配最后一个值。
- 如果同时调用 postValue(“a”)和setValue(“b”),一定是值b被值a覆盖。
setValue()
setValue()的特性如下:
- 此方法只能在主线程里调用
最近遇到一个情况,对同一个LiveData连续多次setvalue时也存在仅分配最后一个值的问题,对调用做了延时但是治标不治本,后续再解决。
解决办法:上述情况出现在用于对主线程传递事件的情况,连续多次调用同一个接口,用LiveData传递接口返回事件到主线程就会存在较短时间内对同一个LiveData对象赋值而LiveData只抛最后一次事件到主线程的情况,解决方法见如下链接
把 LiveData 用于事件传递那些坑
网友评论