Jetpack之LiveData你所需要的一切

基本概念

  • LiveData是一种具有生命周期感知能力的可观察数据持有类
  • LiveData可以保证屏幕上的显示内容和数据一直保持同步

特点

  • LiveData了解UI界面的状态,如果activity不在屏幕上显示,livedata不会触发没必要的界面更新,如果activity已经被销毁,会自动清空与observer的连接
    -LiveData是一个LifecycleOwner,他可以直接感知activity或fragment的生命周期

可解决什么问题

  1. 感知生命周期,在active的时候接收变化
  2. 可以感知数据的变化并体现到UI上
  3. 取代eventbus,在不同界面间通过map+观察者可实现数据发送和接收

使用

class MainViewModel : BaseViewModel() {
		//定义数据
	    val upgradeRsp = MutableLiveData<AppUpdateRspData>()

	    fun getData(){
	    //通过网络或者数据库等拿到数据后,子线程postValue(),主线程setValue()
	    	upgradeRsp.postValue(data)
	    }
}

//这里是在Fragment中观察数据变化,如果是activity中的话则viewLifrcycleOwner换成this即可                upgradeRsp.observe(viewLifecycleOwner, Observer {
				//更新UI等逻辑
             		
                })

工作原理

observe()方法开始跟到源码

    @MainThread
    public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
    	//必须是主线程,否则报错
        assertMainThread("observe");
        //当前生命周期必须没有被销毁,否则无意义
        if (owner.getLifecycle().getCurrentState() == DESTROYED) {
            // ignore
            return;
        }
        LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);
        ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);
        if (existing != null && !existing.isAttachedTo(owner)) {
            throw new IllegalArgumentException("Cannot add the same observer"
                    + " with different lifecycles");
        }
        if (existing != null) {
            return;
        }
        //这句代码就很熟悉了,上一篇文章说LifeCycle完成观察者对被观察者的订阅
        owner.getLifecycle().addObserver(wrapper);
    }
    class LifecycleBoundObserver extends ObserverWrapper implements GenericLifecycleObserver {
        @NonNull
        final LifecycleOwner mOwner;

        LifecycleBoundObserver(@NonNull LifecycleOwner owner, Observer<? super T> observer) {
            super(observer);
            mOwner = owner;
        }

        @Override
        boolean shouldBeActive() {
        //至少是STARTED状态,根据上一篇文档底部的图,即onStart()/onResume()/onPause()生命周期中,即为`活跃`
            return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);
        }
        @Override
        public void onStateChanged(LifecycleOwner source, Lifecycle.Event event) {
        //如果是销毁状态则移除观察者,防止内存泄漏
            if (mOwner.getLifecycle().getCurrentState() == DESTROYED) {
                removeObserver(mObserver);
                return;
            }
            activeStateChanged(shouldBeActive());
        }
}
        @Override
        public void onStateChanged(LifecycleOwner source, Lifecycle.Event event) {
        //如果是销毁状态则移除观察者,防止内存泄漏
            if (mOwner.getLifecycle().getCurrentState() == DESTROYED) {
                removeObserver(mObserver);
                return;
            }
            activeStateChanged(shouldBeActive());
        }
}
        void activeStateChanged(boolean newActive) {
            if (newActive == mActive) {
                return;
            }
            // immediately set active state, so we'd never dispatch anything to inactive
            // owner
            mActive = newActive;
            boolean wasInactive = LiveData.this.mActiveCount == 0;
            LiveData.this.mActiveCount += mActive ? 1 : -1;
            if (wasInactive && mActive) {
                onActive();
            }
            if (LiveData.this.mActiveCount == 0 && !mActive) {
                onInactive();
            }
            if (mActive) {
                dispatchingValue(this);
            }
        }
//如果指定了某个观察者,则只Nofify它,否则遍历所有的观察者一个个Notify之
    void dispatchingValue(@Nullable ObserverWrapper initiator) {
        do {
            mDispatchInvalidated = false;
            if (initiator != null) {
                considerNotify(initiator);
                xxxxxxx
            } else {
                for (Iterator<Map.Entry<Observer<? super T>, ObserverWrapper>> iterator =
                        mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {
                    considerNotify(iterator.next().getValue());
                    xxxxxxx
                
                }
            }
        } while (mDispatchInvalidated);
    }
    private void considerNotify(ObserverWrapper observer) {
        if (!observer.mActive) {
            return;
        }
        // Check latest state b4 dispatch. Maybe it changed state but we didn't get the event yet.
        //
        // we still first check observer.active to keep it as the entrance for events. So even if
        // the observer moved to an active state, if we've not received that event, we better not
        // notify for a more predictable notification order.
        if (!observer.shouldBeActive()) {
            observer.activeStateChanged(false);
            return;
        }
        if (observer.mLastVersion >= mVersion) {
            return;
        }
        observer.mLastVersion = mVersion;
        //noinspection unchecked
        //没错,就回调了接口的这个方法,终于可以被回调到了!
        observer.mObserver.onChanged((T) mData);
    }

到这里就讲清楚了上面说的第一个问题"感知生命周期的变化",在活跃的时候接收监听,销毁的时候移除观察者。

setValue()和postValue()

LiveData发送事件有2个方法:setValue()和postValue(),其中setValue()方法只能在主线程发,而postValue()方法可以在子线程发,Observer的onChange()始终在主线程

注释说的很清楚,只能在主线程上调用

    /**
     * Sets the value. If there are active observers, the value will be dispatched to them.
     * <p>
     * This method must be called from the main thread. If you need set a value from a background
     * thread, you can use {@link #postValue(Object)}
     *
     * @param value The new value
     */
    @MainThread
    protected void setValue(T value) {
        assertMainThread("setValue");
        //发送一次mVersion+1,有点类似于list的modify
        mVersion++;
        mData = value;
        //上面已经分析过了,这个方法传参为null,则所有活跃状态的观察者都会被分发,并回调到onChanged()
        dispatchingValue(null);
    }
    protected void postValue(T value) {
        boolean postTask;
        synchronized (mDataLock) {
            postTask = mPendingData == NOT_SET;
            mPendingData = value;
        }
        if (!postTask) {
            return;
        }
//和setValue差不多,只不过调用了postMainThread()方法跑去主线程了,可以继续往下跟        ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);
    }
    @Override
    public void postToMainThread(Runnable runnable) {
        if (mMainHandler == null) {
            synchronized (mLock) {
                if (mMainHandler == null) {
                    mMainHandler = new Handler(Looper.getMainLooper());
                }
            }
        }
        //noinspection ConstantConditions
        mMainHandler.post(runnable);
    }
    private final Runnable mPostValueRunnable = new Runnable() {
        @Override
        public void run() {
            Object newValue;
            synchronized (mDataLock) {
                newValue = mPendingData;
                mPendingData = NOT_SET;
            }
            //noinspection unchecked
            //最终postValue()还是调用到setValue()
            setValue((T) newValue);
        }
    };

这个方法是可以在子线程中发数据的,但是我们最后的onChanged()方法却始终在主线程的,这是怎么做到的呢?看到这两句代码应该就很明白了
mMainHandler = new Handler(Looper.getMainLooper());
mMainHandler.post(runnable);

LivedataBus粘性事件

通过一个集合统一管理所有的LiveData

原来的执行顺序new LiveData–>绑定observer–>setValue执行onChanged
完美!


		MutableLiveData<String> currentName = xxxx;
        //取出livedata完成订阅
        model.getCurrentName().observe(this,new Observer<String>(){
            @Override
            public void onChanged(String s) {
                nameTextView.setText(s);
            }
        });

        btn.setOnClickListener(new View.OnClickListener(){
            @Override
            public void onClick(View v) {
                String anotherName="jett"+(i++);
                model.getCurrentName().setValue(anotherName);
            }
        });

但是可能会有这样的情况出现:
new LiveData–>setValue执行onChanged–>绑定observer

比如这样:
先发送消息了------>

            Intent intent = new Intent(this, TestLiveDataBusActivity.class);
            startActivity(intent);
            new Thread(){
                @Override
                public void run() {
                    for (int i = 0; i < 20; i++) {
                        //发送消息
                        LiveDataBus.getInstance().with("data", String.class).postValue("jett");
                        Log.e(TAG, "run:已发送 ");
                        try {
                            Thread.sleep(1000);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }.start();
        }

然后第二个界面才走onCreate()—>绑定观察者

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_livedatabus);
        Log.e(TAG, "onCreate: " );
        LiveDataBusX.getInstance().with("data", String.class)
                    .observe(this, new Observer<String>() {
                        @Override
                        public void onChanged(String s) {
                            Log.e(TAG, "onChanged: "+s);
                            if(s!=null)
                            Toast.makeText(TestLiveDataBusActivity.this, s, Toast.LENGTH_SHORT).show();
                        }
                    });
    }

于是就出现了EventBus粘性事件类似的事情,至于如何解决,也不难,注意下面个方法:
在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Alex_ChuTT

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值