在上一篇文章中,Lifecycle组件使得普通类能随时感知Activity/Fragment周期的变化,以此来执行对应周期的逻辑
而在本文中,LiveData组件使得Activity/Fragment能够随时感知到界面数据的变化,以此来执行对应的界面数据更新
LiveData的基本操作
public class MainActivity extends AppCompatActivity {
private static final String TAG = "LiveDataDemo";
private MutableLiveData<String> liveData1;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
liveData1 = new MutableLiveData<>();
liveData1.observe(this, new Observer<String>() {
@Override
public void onChanged(String info) {
Log.i(TAG, "LiveData1 onChanged: " + info);
}
});
liveData1.postValue("MutableLiveData基本使用Demo");
}
MutableLiveData是安卓原生提供给我们的LiveData实现类
public class MutableLiveData<T> extends LiveData<T> {
public MutableLiveData(T value) {
super(value);
}
public MutableLiveData() {
super();
}
@Override
public void postValue(T value) {
super.postValue(value);
}
@Override
public void setValue(T value) {
super.setValue(value);
}
}
其实细心的小伙伴已经发现LiveData虽然定义成抽象类,但是它里面并没有任何抽象方法,那么我们可以完全自定义LiveData类
public class LiveDataImpl extends LiveData<LiveDataImpl> {
private int mData;
public int getmData() {
return mData;
}
public void setmData(int mData) {
this.mData = mData;
postValue(this);
}
}
由于LiveData主要是用来绑定Activity/Fragment,用做LiveData数据变更的时候能够提醒到Activity/Fragment,在这查看一下LiveData的observer方法
liveData1.observe(this, new Observer<String>() {
@Override
public void onChanged(String info) {
Log.i(TAG, "LiveData1 onChanged: " + info);
}
});
observer方法需要传入LifecycleOwner对象和Observer对象,前者从名字也能理解是生命周期的拥有者,也就是说Activity/Fragment,因此这里直接传入this,而后者Observer相当于一个回调对象(观察者),在数据变更的时候会调用该对象的回调方法(观察到了数据变化),也就是onChanged,并把最新观察到的数据作为入参传入。
回到MutableLiveData类,这里调用了postValue用来更新LiveData中的数据,观察者感知到数据的变化后就会执行onChanged并把最新的数据回传回来,界面只需要在onChanged方法中执行对应界面数据的刷新即可。
Transformations.map方法
在很多时候,获取数据后并不会直接就显示到界面上,需要对数据做一些处理(比如加上关键字之类的),对于这种情况,可以有两种方案:
- 在onChanged方法中直接对数据处理,然后在执行Activity/Fragment的界面刷新
- 使用Transformations.map将当前的LiveData1更新的数据回传的给另一个LiveData2,LiveData2对数据进行加工,Activity/Fragment只要观察LiveData2的数据变化即可
下面就是第二种方案的例子:
//Transformations.map的Demo
LiveData<String> transformLiveData = Transformations.map(liveData1, new Function<String, String>() {
@Override
public String apply(String input) {
return "Transformations.map处理后: " + input;
}
});
transformLiveData.observe(this, new Observer<Object>() {
@Override
public void onChanged(Object info) {
Log.i(TAG, info.toString());
}
});
liveData1.postValue("Transformations.map的Demo: ");
Tranformations.map实现了LiveData1到LiveData2的转变,通过Function的输入输出来负责数据的加工处理
对于函数式不熟悉的小伙伴可以查看浅谈函数式编程,需要注意的是,这里用到的function是androidx.arch.core.util.Function,而不是java.util.function.Function。
Transformations.switchMap
有时候需要使用的LiveData是不确定的,这个时候可以使用Transformations.switchMap来做一层判断,输出所需要的LiveData
使用Transformations.switchMap需要:
- LiveData1和LiveData2两个数据,同时通过observer绑定对应的Activity/Fragment
- 使用第三个LiveData3来接收判断所需要的入参,同时通过observer绑定对应的Activity/Fragment
- 使用LiveData4来接收最终所得的LiveData,同时通过observer绑定对应的Activity/Fragment
- LiveData1、LiveData2和LiveData3更新数据
业务只需要在LiveData3中传入不同的值,switch方法会匹配到对应的LiveData1/LiveData2输出并赋值给LiveData4
liveData1 = new MutableLiveData<>();
liveData1.observe(this, new Observer<String>() {
@Override
public void onChanged(String info) {
Log.i(TAG, "LiveData1 onChanged: " + info);
}
});
liveData1.postValue("MutableLiveData基本使用Demo");
//Transformations.switchMap
liveData2 = new MutableLiveData<>();
liveData2.observe(this, new Observer<String>() {
@Override
public void onChanged(String info) {
Log.i(TAG, "liveData2 onChanged: " + info);
}
});
MutableLiveData<Boolean> switchLiveData = new MutableLiveData<>();
LiveData<String> transformSwitchLiveData = Transformations.switchMap(switchLiveData, new Function<Boolean, LiveData<String>>() {
@Override
public LiveData<String> apply(Boolean input) {
if (input) {
return liveData1;
} else {
return liveData2;
}
}
});
transformSwitchLiveData.observe(this, new Observer<String>() {
@Override
public void onChanged(String info) {
Log.i(TAG, "transformLiveData onChanged: " + info);
}
});
switchLiveData.postValue(false);
liveData1.postValue("liveData1 switchMap");
liveData2.postValue("liveData2 switchMap");
}