LiveData
创始人
2024-01-28 14:17:20

LiveData是一个抽象类,那么我们从简单的MutableLiiveData开始剖析,先看源码

源码太简洁了,就是继承LiveData,然后重写了父类的方法,并且没有多余的操作,都是直接使用父类方法里的逻辑,那我们就根据这几个方法,来一点一点看liveData

构造函数,也就是传一个泛型T的对象

 就是做一个初始化赋值,有一个mVersion = START_VERSION+1,也很好理解了

来到postValue

   protected void postValue(T value) {boolean postTask;synchronized (mDataLock) {postTask = mPendingData == NOT_SET;mPendingData = value;}if (!postTask) {return;}ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);}

synchronized对这个代码块上锁,代码块里就是赋值,防止多个线程同时赋值,所以要上锁,第一次的时候mPendingData == NO_SET肯定是true,因为初始化的时候

volatile Object mPendingData = NOT_SET;

然后给mPendingData赋新值,然后post一个任务,这个任务的代码如下

 private final Runnable mPostValueRunnable = new Runnable() {@SuppressWarnings("unchecked")@Overridepublic void run() {Object newValue;synchronized (mDataLock) {newValue = mPendingData;mPendingData = NOT_SET;}setValue((T) newValue);}};

同样要上锁,防止多线程同时修改值,将mPendingData赋值给newValue,然后又mPendingData = NOT_SET,这里其实有个线程切换,后面剖析,这里及继续追踪到setValue

  @MainThreadprotected void setValue(T value) {assertMainThread("setValue");mVersion++;mData = value;dispatchingValue(null);}

有个注解@MainThread,也就是说这个方法一定要在主线程中调用,方法就是将值赋值给mData,这个mData就是构造方法里的mData,它一直在主线程更新,也就是说就算有多线程更新,那么也是一次一次的切换到主线程再更新mData的值

dispatchingValue()的核心代码

        do {mDispatchInvalidated = false;if (initiator != null) {considerNotify(initiator);initiator = null;} else {//遍历观察者,分别通知他们for (Iterator, ObserverWrapper>> iterator =mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {considerNotify(iterator.next().getValue());if (mDispatchInvalidated) {break;}}}} while (mDispatchInvalidated);

其实就是观察者,然后通知他们,通知的方法considerNotify

 private void considerNotify(ObserverWrapper observer) {if (!observer.mActive) {  //判断观察者是否处于活跃状态return;}if (!observer.shouldBeActive()) {observer.activeStateChanged(false);return;}if (observer.mLastVersion >= mVersion) {    //记得versionCode不,这是一个判断是否匹配return;}observer.mLastVersion = mVersion;  //versionCode不同,就赋值 observer.mObserver.onChanged((T) mData);    //通知观察者更新}

构建liveData的观察者:

//构建liveData的观察者,这里为什么要传一个LifecycleOwner呢,其实就是要知道LifecycleOwner 的生 //命周期,因为liveDta是在activty/fragment在活跃状态的时候才会更新值,也就是说其实liveData也观察了activity/fragment的生命周期
class LifecycleBoundObserver extends ObserverWrapper implements LifecycleEventObserver {@NonNullfinal LifecycleOwner mOwner;//构造函数LifecycleBoundObserver(@NonNull LifecycleOwner owner, Observer observer) {super(observer);mOwner = owner;}@Overrideboolean shouldBeActive() {return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);    //判断被观察者的最新状态}//观察了lifecycleOwner的生命周期状态,所以说虽然liveData是被观察者,但是它作为被观察者通样也是一个观察者@Overridepublic void onStateChanged(@NonNull LifecycleOwner source,@NonNull Lifecycle.Event event) {//页面当前状态Lifecycle.State currentState = mOwner.getLifecycle().getCurrentState();if (currentState == DESTROYED) {    //页面都没了removeObserver(mObserver);return;}Lifecycle.State prevState = null;//状态改变while (prevState != currentState) {prevState = currentState;activeStateChanged(shouldBeActive());currentState = mOwner.getLifecycle().getCurrentState();}}@Overrideboolean isAttachedTo(LifecycleOwner owner) {return mOwner == owner;}@Overridevoid detachObserver() {        //不用观察了mOwner.getLifecycle().removeObserver(this);}}

其实liveDta是作为一个被观察者,当它的mData发生有效改变的时候,通知他的观察者集合们,同时liveData也是一个观察者啊,它时刻观察者当前activity/fragment的生命周期变化

------------------------------------------------------------

回到postValue,我们都知道在主线程更新liveData可以用setValue,但是在非主线程要更改liveData的值,需要用postValue,我们在上面看到了,就算用postValue,最终也是切到主线程调用setValue,那么我们就来追踪一些这个切换的过程

 因为在子线程中调用,所以我们先锁住我们的判断,防止值被改变,导致判断不准确,当值是改变了,那么核心就来到了

 ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);

我们在子线程,这里有个postToMainThread,我们都知道线程的切换怎么都离不开handler,继续追踪,getInstance,会不会是一个单例呢,没错就是一个单例,切线程的方法postToMainThread

追踪发现一个DefaultTaskExecutor

    @Overridepublic void postToMainThread(Runnable runnable) {if (mMainHandler == null) {synchronized (mLock) {if (mMainHandler == null) {mMainHandler = createAsync(Looper.getMainLooper());}}}//noinspection ConstantConditionsmMainHandler.post(runnable);}

就是创建一个Handler,只创建一次哈,创建Handler用主线程的Looper,这样runnable就post到主线程的Looper里面的MessageQueue中,主线程Looper循环从MessageQueue中取出message,并交给message.target也就是发送message的handler处理

相关内容

热门资讯

埃菲尔铁塔在哪 中国仿建埃菲尔... 2019年4月26日,广西南宁市,街头惊现一座巨型山寨版埃菲尔铁塔,高约20米,白色塔身,造型逼真,...
苗族的传统节日 贵州苗族节日有... 【岜沙苗族芦笙节】岜沙,苗语叫“分送”,距从江县城7.5公里,是世界上最崇拜树木并以树为神的枪手部落...
不用电脑怎么设置苹果铃声 ip... 需要一个app,加上苹果自带的app即可1、手机下载爱思极速版。因为之前换手机搬移数据时店员帮忙整理...
北京的名胜古迹 北京最著名的景... 北京从元代开始,逐渐走上帝国首都的道路,先是成为大辽朝五大首都之一的南京城,随着金灭辽,金代从海陵王...
应用未安装解决办法 平板应用未... ---IT小技术,每天Get一个小技能!一、前言描述苹果IPad2居然不能安装怎么办?与此IPad不...
长白山自助游攻略 吉林长白山游... 昨天介绍了西坡的景点详细请看链接:一个人的旅行,据说能看到长白山天池全凭运气,您的运气如何?今日介绍...
脚上的穴位图 脚面经络图对应的... 人体穴位作用图解大全更清晰直观的标注了各个人体穴位的作用,包括头部穴位图、胸部穴位图、背部穴位图、胳...
世界上最漂亮的人 世界上最漂亮... 此前在某网上,选出了全球265万颜值姣好的女性。从这些数量庞大的女性群体中,人们投票选出了心目中最美...
猫咪吃了塑料袋怎么办 猫咪误食... 你知道吗?塑料袋放久了会长猫哦!要说猫咪对塑料袋的喜爱程度完完全全可以媲美纸箱家里只要一有塑料袋的响...
埃菲尔铁塔在哪 中国仿建埃菲尔... 2019年4月26日,广西南宁市,街头惊现一座巨型山寨版埃菲尔铁塔,高约20米,白色塔身,造型逼真,...
苗族的传统节日 贵州苗族节日有... 【岜沙苗族芦笙节】岜沙,苗语叫“分送”,距从江县城7.5公里,是世界上最崇拜树木并以树为神的枪手部落...
才高八斗的主人公 三顾茅庐的主... 古代君王在建立自己的政治体系之时,大多会采取一些礼贤下士的手段,对于一些有卓越才能的人放低姿态。因为...
北京的名胜古迹 北京最著名的景... 北京从元代开始,逐渐走上帝国首都的道路,先是成为大辽朝五大首都之一的南京城,随着金灭辽,金代从海陵王...