美文网首页
Transformations和MediatorLiveData

Transformations和MediatorLiveData

作者: 就叫汉堡吧 | 来源:发表于2022-02-26 09:15 被阅读0次
    • 引出MediatorLiveData

      有时候我们需要这么一个场景,有多个LiveData,当其中任何一个LiveData产生变化时我们都要响应某些操作,当然你可以选择每个LiveData都调用observe方法设置相关回调,不过缺点是你会有冗余代码,因为你设置的回调都是一样的逻辑,当有更多的数据源的时候,你需要维护更多的地方同步回调操作。

      所以MediatorLiveData出现了,MediatorLiveData本身也是一个LiveData,通过它我们只需要调用addSource方法添加多个LiveData,然后我们只需要监听MediatorLiveData这一个LiveData即可,其中任何一个数据源发生变化都会回调到MediatorLiveData这一个LiveData的监听回调中。

      比如下面的代码:

      val mediatorLiveData = MediatorLiveData<Any>()
      mediatorLiveData.addSource(liveData01, {
          mediatorLiveData.value = it
      })
      mediatorLiveData.addSource(liveData02, {
          mediatorLiveData.value = it
      })
      mediatorLiveData.observe(this){
          //liveData01或者liveData02其中之一变化都会走到这里
      }
      

      可以看到,在调用addSource方法的时候传入一个Observer回调,你可以在这个回调里做一些别的事情,这个是和第一个LiveData参数是绑定在一起的:

      @MainThread
      public <S> void addSource(@NonNull LiveData<S> source, @NonNull Observer<? super S> onChanged) {
          Source<S> e = new Source<>(source, onChanged);
          Source<?> existing = mSources.putIfAbsent(source, e);
          if (existing != null && existing.mObserver != onChanged) {
              throw new IllegalArgumentException(
                      "This source was already added with the different observer");
          }
          if (existing != null) {
              return;
          }
          if (hasActiveObservers()) {
              e.plug();
          }
      }
      

      e.plug()会把livedata和Observer绑定在一起:

      private static class Source<V> implements Observer<V> {
          final LiveData<V> mLiveData;
          final Observer<? super V> mObserver;
          int mVersion = START_VERSION;
      
          Source(LiveData<V> liveData, final Observer<? super V> observer) {
              mLiveData = liveData;
              mObserver = observer;
          }
      
          void plug() {
              mLiveData.observeForever(this);
          }
      
          void unplug() {
              mLiveData.removeObserver(this);
          }
      
          @Override
          public void onChanged(@Nullable V v) {
              if (mVersion != mLiveData.getVersion()) {
                  mVersion = mLiveData.getVersion();
                  mObserver.onChanged(v);
              }
          }
      }
      

      所以流程就是拿liveData01来说,当liveData01.setValue或者liveData01.postValue方法被调用时,因为liveData01和Source是绑定的,根据LiveData原理,Source的onChanged会被调用,mObserver又是构造时传入的addSource方法的onChange参数,所以就会调用mediatorLiveData.value = it,从而mediatorLiveData的observe回调被触发,达到统一回调的作用。

    • 引出Transformations

      从上面的过程中我们可以发现一些可以封装简化代码的地方,比如构造过程,MediatorLiveData的出现自然是为了统一处理多个数据源,如果恰好你的使用场景又是统一回调处理的话,那么Transformations就可以派上用场了。

      Transformations和MediatorLiveData都是androidx.lifecycle包下的类,Transformations其实就是封装了MediatorLiveData构造的一个工具类,它只有两个静态方法,map和switchMap。

      @MainThread
      public 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;
      }
      

      map方法就是我们上面构造MediatorLiveData的代码,不同的是你可以多设置一个Function,在子数据源回调时对它的结果做进一步的处理后再发送给MediatorLiveData。如果添加多个数据源的话,同样要在map方法之后调用addSource方法进行添加。

      还有一种场景是,在某个LiveData回调之后重新设置一个新的LiveData,即只监听一次旧的LiveData,然后就替换成和上面map方法一样的逻辑了。

      @MainThread
      public 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;
      }
      

      可以看到,上面的source只会使用一次,到了这里的onChanged回调后就移除了,然后添加一个由switchMapFunction.apply方法产生的新的LiveData,使用和map方法中一样的Observer,只不过这里的新的LiveData的回调值没有回调接口可处理,即y的值是原封不动地传给MediatorLiveData的回调的。

    相关文章

      网友评论

          本文标题:Transformations和MediatorLiveData

          本文链接:https://www.haomeiwen.com/subject/mghqrrtx.html