一、定义
- LiveData是一个数据持有类,持有数据可以被观察者订阅。
- LiveData能够感知组件(Fragment,Activity、Service)的生命周期,当数据发生变动时只会通知处于激活状态的组件。
- 当组件处于DESTROYED状态时,观察者对象会被自动清除,减少内存泄漏。
二、使用
添加相关依赖:
implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0'
demo很简单,点击按钮获取当前时间,更新时间LiveData,监听到后刷新UE显示。
public class LiveDataActivity extends AppCompatActivity {
private static final String TAG = "LiveDataActivity";
private Button mBtnRefreshTime;
private TextView mTvTime;
//1、创建LiveData实例
private MutableLiveData<String> mTimeData = new MutableLiveData<>();
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_livedata);
initView();
//2、添加监听,设置TextView显示
mTimeData.observe(this, new Observer<String>() {
@Override
public void onChanged(String newTime) {
//4、收到数据变更,更新UE显示
mTvTime.setText(newTime);
}
});
}
private void initView() {
mTvTime = findViewById(R.id.tv_time);
mBtnRefreshTime = findViewById(R.id.btn_refresh_time);
mBtnRefreshTime.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
//3、更新LiveData数据
mTimeData.setValue(getCurrentTime());
}
});
}
/**
* 获取当前时间,格式:HH:mm:ss
* @return
*/
private String getCurrentTime() {
long currentTime = System.currentTimeMillis();
Date date = new Date(currentTime);
SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");
String time = sdf.format(date);
return time;
}
}
三、常用方法
- Transformations.map:从一个LiveData转换到另外一个LiveData。如下面例子,经过transformLiveData的加工,以后显示时间字符串都会加上:“current time is :”。
LiveData<String> transformLiveData = Transformations.map(mTimeData, new Function<String, String>() {
@Override
public String apply(String input) {
return "current time is :" + input;
}
});
transformLiveData.observe(this, new Observer<String>() {
@Override
public void onChanged(String newTime) {
mTvTime.setText(newTime);
}
}
-
Transformations.switchMap:用一个LiveData的value改变来触发另外一个LiveData的获取。如下面例子:
用法1:mTriggerLiveData是一个布尔值,当mTriggerLiveData改变时,nameLiveData 会获取最新的name数据,不过,name数据如果一直没改动的话,无论mTriggerLiveData改变多少次,observe中的打印只会打印一次。
用法2:根据mTriggerLiveData的值来返回不同的LiveData。
//定义触发数据
private MutableLiveData<Boolean> mTriggerLiveData = new MutableLiveData<Boolean>();
//用法1:
LiveData<String> nameLiveData = Transformations.switchMap(mTriggerLiveData, new Function<Boolean, LiveData<String>>() {
@Override
public LiveData<String> apply(Boolean input) {
LogUtil.i(TAG, "-----apply input: " + input);
return mDataViewModel.getName();
}
});
nameLiveData.observe(this, new Observer<String>() {
@Override
public void onChanged(String name) {
LogUtil.i(TAG, "---------- name: " + name);
}
});
//用法2:
LiveData<String> targetLiveData= Transformations.switchMap(mTriggerLiveData, new Function<Boolean, LiveData<String>>() {
@Override
public LiveData<String> apply(Boolean input) {
LogUtil.i(TAG, "##### apply input: " + input);
if (input) {
return mDataViewModel.getName();
} else {
return mDataViewModel.getPwd();
}
}
});
targetLiveData.observe(this, new Observer<String>() {
@Override
public void onChanged(String result) {
LogUtil.i(TAG, "####### result: " + result);
}
});
- MediatorLiveData:继承自MutableLiveData,将多个LiveData合并在一起,一并监听多个变量的变化。
//viewmodel中定义name和pwd,然后用一个loginInfo监听这两个值得变化
private MutableLiveData<String> name = new MutableLiveData<>();
private MutableLiveData<String> pwd = new MutableLiveData<>();
private MediatorLiveData<String> loginInfo = new MediatorLiveData<>();
//添加到MediatorLiveData中
loginInfo.addSource(name, new Observer<String>() {
@Override
public void onChanged(String name) {
loginInfo.setValue(name);
}
});
loginInfo.addSource(pwd, new Observer<String>() {
@Override
public void onChanged(String pwd) {
loginInfo.setValue(pwd);
}
});
//Activity中使用
mDataViewModel.getLoginInfo().observe(this, new Observer<String>() {
@Override
public void onChanged(String loginInfo) {
LogUtil.i(TAG, "loginInfo: " + loginInfo);
}
});
-
onActive:当Active状态的观察者的数量从0变为1时会调用onActive方法,即当LiveData对象具有Active状态的观察者时调用onActive方法。
-
onInactive:当LiveData对象没有任何Active状态的观察者时调用onInactive方法。
-
setValue:给LiveData设置新的数据,该方法必须在主在线中调用,回调在主线程。
-
postValue:给LiveData设置新的数据,可以在主线程中调用,也可以在子线程中调用,回调在主线程。