美文网首页
Transformations和MediatorLiveData

Transformations和MediatorLiveData

作者: Horps | 来源:发表于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