Android LiveData Transformations

官方文档:https://developer.android.com/reference/android/arch/lifecycle/Transformations

在使用LiveData时,有时候我们想改变LiveData的值在LiveData通知其Observers之前,或者在有些时候我们的数据源Repository会返回不同的LiveData实例,我们需要一种数据转换的功能帮助我们去转换不同数据层的数据,而Transformations就是这样一个工具。

Transformations主要有两个方法

  1. LiveData map (LiveData source, Function func)

    提供一个方法去在LiveData.setValue之前对value进行相应的转换和处理

  2. LiveData switchMap (LiveData trigger, Function func)

    与map类似,但是是对LiveData进行转换,而不是对应的value,将两个LiveData桥接起来,其scope也会相应传递

Translations.map

我们有两个LiveData在一个viewModel中,其中一个userLiveData负责持有user数据,另一个负责与UI进行绑定。每次我们setUser的时候都会触发Transformations.map()将我们的user数据转换成我们需要在UI上展示的文字string

private val LiveData userLiveData = ...;val LiveData userName = Transformations.map(userLiveData, user -> {     return user.firstName + " " + user.lastName })fun setUser(user:User) {    userLiveData.value = user}

Translations.switchMap

我们依旧创建两个LiveData在viewModel中,userIdLiveData作为trigger,每次setUserId触发时就会从repository获取对应新的id的user内容,通过switchMap传递给userLiveData

MutableLiveData userIdLiveData = ...;LiveData userLiveData = Transformations.switchMap(userIdLiveData, id ->     repository.getUserById(id));void setUserId(String userId) {  this.userIdLiveData.setValue(userId);}

如果我们不在这里使用switchMap的话,由于我们的repository每次返回的都是一个新的LiveData instance,会导致view observe多个LiveData的情形出现,而switchMap会保证view observe的LiveData的是同一个

Google官方也提醒我们在使用LiveData的时候要避免对外暴露一个var类型的LiveData或者MutableLiveData,以避免重复observe

Transformations 源码

Transformations源码比较简单,如下:

@MainThreadpublic static <X, Y> LiveData<Y> map(        @NonNull LiveData<X> source,        @NonNull final Function<X, Y> mapFunction) {    final MediatorLiveData<Y> result = new MediatorLiveData<>();    result.addSource(source, new Observer<X>() {        @Override        public void onChanged(@Nullable X x) {            result.setValue(mapFunction.apply(x));        }    });    return result;}

可以看到主要就是在setValue前执行了mapFunction并且将新的值赋值给LiveData

@MainThreadpublic static <X, Y> LiveData<Y> switchMap(        @NonNull LiveData<X> source,        @NonNull final Function<X, LiveData<Y>> switchMapFunction) {    final MediatorLiveData<Y> result = new MediatorLiveData<>();    result.addSource(source, new Observer<X>() {        LiveData<Y> mSource;        @Override        public void onChanged(@Nullable X x) {            LiveData<Y> newLiveData = switchMapFunction.apply(x);            if (mSource == newLiveData) {                return;            }            if (mSource != null) {                result.removeSource(mSource);            }            mSource = newLiveData;            if (mSource != null) {                result.addSource(mSource, new Observer<Y>() {                    @Override                    public void onChanged(@Nullable Y y) {                        result.setValue(y);                    }                });            }        }    });    return result;}

switchMap主要会进行重新绑定的操作,如果从switchMapFunction中获得的LiveData发生了变化,则会重新进行observe,从而避免上文提到的重复observe的问题

MediatorLiveData

我们从源码中可以看到两个方法都使用了MediatorLiveData这个类型。这个类和MutableLiveData一样都继承自LiveData. 主要是帮助我们解决这样一种case:我们有多个LiveData实例,这些LiveData的value发生变更时都需要通知某一个相同的LiveData。

LiveData liveData1 = ...;LiveData liveData2 = ...;MediatorLiveData liveDataMerger = new MediatorLiveData<>();liveDataMerger.addSource(liveData1, value -> liveDataMerger.setValue(value));liveDataMerger.addSource(liveData2, value -> liveDataMerger.setValue(value)); 

我们还可以在监听value变化的过程中根据需要取消对某个LiveData的observe

liveDataMerger.addSource(liveData1, new Observer() {    //...       @Override    public void onChanged(@Nullable Integer s) {                val liveData1IsUseless = //... some logic                liveDataMerger.setValue(s);                if (liveData1IsUseless) {          liveDataMerger.removeSource(liveData1);        }    } });

更多相关文章

  1. android 将SharedPreferences做成简单工具
  2. android webkit 打开debug调试信息
  3. Android之SharedPreferences详解
  4. Android教程之android数据库编程
  5. android之listview内存优化
  6. Android(安卓)Bundle类
  7. Android(安卓)Bundle类
  8. Android(安卓)Bundle类
  9. mybatisplus的坑 insert标签insert into select无参数问题的解决

随机推荐

  1. 19、从头学Android之Android的数据存储--
  2. 如何适应android碎片化的屏幕
  3. android string.setSpan
  4. Android(安卓)Launcher抽屉类SlidingDraw
  5. Java之IO流操作
  6. 如何实现Android桌面小部件(二)
  7. [转载]Android触屏滑动事件总结 (2011-08
  8. android 异步显示View
  9. android PreferenceActivity结合Preferen
  10. Roman Guy的Android Trick系列文章笔记