MediatorLiveData源码解析

作用

  • MediatorLiveData 可以接管普通的 LiveData,使得当 LiveData 有数据更新的时候,MediatorLiveData 也能够 “收到响应”

实例

	    class mainactivity : appcompatactivity{
	    	private val originData = MutableLiveData<String>()
		    private val mediatorLiveData = MediatorLiveData<String>()
	
    		override fun onCreate(savedInstanceState: Bundle?) {
 
			mediatorLiveData.addSource(originData, Observer<String>{
	        	Log.e("==>liveData","addSourceObserver:$it")
	    	})
	     
	     	btn.setOnClickListener {
	        	originData.value = "Hello"
	     	}
		}

说明

  • 1.构建一个 MediatorLiveData对象,并通过addSource()将originData对象传入,然后添加回调方法,当我们点击按钮的时候,设置originData的值,最后在控制台应该输出:==>liveData: addSourceObserver:Hello。但是最后发现却没有输出,那是因为MediatorLiveData对象没有被“激活”,mediatorLiveData需要调用observe() 或者 observeForever() 方法来进行激活

       override fun onCreate(savedInstanceState: Bundle?) {
           
           
               ... ...
               mediatorLiveData.observe(this, Observer {
           
           
                   Log.e("==>liveData","mediatorLiveData:$it")
               })
               ... ...
           }
    

说明

  • 当再次点击按钮时,其输出不是:

       ==>liveData: addSourceObserver:Hello
       ==>liveData: mediatorLiveData:Hello
    

    实际输出是:

        ==>liveData: addSourceObserver:Hello
    

那么为什么会这样了,那我们看看源码到底发生了什么?

			     private static class Source<V> implements Observer<V> {
	        //传递过来的liveData
	        final androidx.lifecycle.LiveData<V> mLiveData;
	        //构建的observer
	        final Observer<? super V> mObserver;
	        //当前observer的版本
	        int mVersion = START_VERSION;
	
	        /**
	         * 通过构造函数获取传递进来的livedata以及观察者
	         * @param liveData
	         * @param observer
	         */
	        Source(LiveData<V> liveData, final Observer<? super V> observer) {
	            mLiveData = liveData;
	            mObserver = observer;
	        }
	
	        /**
	         * 让传递进来的livedata添加一个不对生命周期进行管理的观察者
	         */
	        void plug() {
	            mLiveData.observeForever(this);
	        }
	        /**
	         * 让传递进来的livedata移除观察者
	         */
	        void unplug() {
	            mLiveData.removeObserver(this);
	        }
	
	
	        /**
	         * 传递进来的livedata添加了一个不进行生命周期管理的观察者(source),
	         * 当livedata设置数据数据时会去通知所有的观察者,包括source
	         * source就会回调构建的observer的onChanged()方法,
	         * 那么livedata设置数据后那么observer就会获取到数据
	         * @param v
	         */
	        @Override
	        public void onChanged(@Nullable V v) {
	            if (mVersion != mLiveData.getVersion()) {
	                mVersion = mLiveData.getVersion();
	                mObserver.onChanged(v);
	            }
	        }
	    }

说明

  • 1.继承于Observer,是Observer的子类

  • 2.持有传递进来的livedata和observer对象的引用

  • 3.plug():让传递进来的livedata添加一个不对生命周期进行管理的观察者

  • 4.unplug():传递进来的livedata移除观察者。

  • 5.onChanged():当传递进来的livedata有数据要通知所有观察者时,当前Observer会触发onChanged()方法,之后就会发送给传递进来的mObserver

    	  //map  能保证在遍历的时候可以修改集合   key:LiveData  value:Source
    	    private SafeIterableMap<androidx.lifecycle.LiveData<?>,  Source<?>> mSources = new SafeIterableMap<>();
    	
    	    /**
    	     * 添加获取一个livedata
    	     * @param source
    	     * @param onChanged
    	     * @param <S>
    	     */
    	    @MainThread
    	    public <S> void addSource(@NonNull androidx.lifecycle.LiveData<S> source, @NonNull Observer<? super S> onChanged) {
    	        //构建source对象(Observer),封装了传递进来的livedata和observer
    	        Source<S> e = new Source<>(source, onChanged);
    	        //若同一个livedata的观察者不是同一个将会抛异常
    	        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;
    	        }
    	        //需要有激活状态的观察者才可以添加source观察者
    	        // 那么要是我先调用了addSource 再调用observer()那么不是也不能触发e.plug()了吗
    	        if (hasActiveObservers()) {
    	            e.plug();
    	        }
    	    }
    	
    	    /**
    	     * Stops to listen the given {@code LiveData}.
    	     *
    	     * @param toRemote {@code LiveData} to stop to listen
    	     * @param <S>      the type of data hold by {@code source} LiveData
    	     */
    	    @MainThread
    	    public <S> void removeSource(@NonNull androidx.lifecycle.LiveData<S> toRemote) {
    	        Source<?> source = mSources.remove(toRemote);
    	        if (source != null) {
    	            source.unplug();
    	        }
    	    }
    	
    	    /**
    	     * 1.重写了onActive()方法
    	     * 2.触发条件:当livedata有第一个观察者后调用
    	     * 3.因此当我们先调用source(),然后再调用observer(),也可以触发plug(),
    	     * 让source作为观察者被添加到livedata中
    	     */
    	    @CallSuper
    	    @Override
    	    protected void onActive() {
    	        for (Map.Entry<androidx.lifecycle.LiveData<?>, Source<?>> source : mSources) {
    	            source.getValue().plug();
    	        }
    	    }
    	
    	    /**
    	     * 1.重写了onInactive()方法
    	     * 2.触发条件:当livedata没有处于激活状态的观察者后
    	     * 3.解除绑定
    	     */
    	    @CallSuper
    	    @Override
    	    protected void onInactive() {
    	        for (Map.Entry<androidx.lifecycle.LiveData<?>, Source<?>> source : mSources) {
    	            source.getValue().unplug();
    	        }
    	    }
    

说明

  • 1.mSources:以livedata为key,以封装了livedata和observer的Source为value
  • 2.addSource():将livedata和observer封装成Source对象,然后存储到mSources中,然后调用hasActiveObservers()判断是否有激活状态的观察者,若有则调用e.plug()给livedata注册一个不进行生命周期绑定的观察者
  • 3.removeSource():从mSources中移除对应的观察者
  • 4.onActive():当有第一个处于激活状态的观察者的时候触发,因为有可能先调用addSource(),然后再调用observer(),导致在addSource()中中无法触发e.plug(),那么只有在这里触发进行注册了。
  • 5.onInactive() :livedata没有处于激活状态的观察者后触发,可以用于解除观察者的绑定
从源码知道,想要addSource()触发观察者回调,需要先让MediatorLiveData至少有一个观察者处于激活状态才可以,所以我们需要调用observer()/observerforever()添加一个处于激活状态的观察者才可以让source通过传递进来livedata注册观察者,从而能接收到传递进来的livedata的数据变化
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值