LiveData setValue和postValue源码解析

LiveData描述

LiveData 是一款基于观察者模式的可感知生命周期的核心组件。LiveData 为界面代码 (Observer)的监视对象 (Observable),当 LiveData 所持有的数据改变时,它会通知相应的界面代码进行更新。同时,LiveData 持有界面代码 Lifecycle 的引用,这意味着它会在界面代码(LifecycleOwner)的生命周期处于 started 或 resumed 时作出相应更新,而在 LifecycleOwner 被销毁时停止更新。通过 LiveData,我们可以方便地构建安全性更高、性能更好的高响应度用户界面。

平时我们使用LiveData的时候,需要更新数据的时候,LiveData提供了两种更新数据的方式:

setvalue和postValue的区别

setValue(T value)

postValue(T value)

这两个方法区别是:setValue(T value) 只能在主线程中调用,postValue(T value)可以在任何线程中调用

源码分析:

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

1.通过注解@MainThread我们可以看到setValue这个方法是主线程中进行的

2.在第一步调用了assertMainThread这个方法,我们通过源码可以看出 判断当前的线程是否是在主线程中如果不是则抛出IllegalStateException,告诉开发者必须在主线程中进行开发

  static void assertMainThread(String methodName) {
        if (!ArchTaskExecutor.getInstance().isMainThread()) {
            throw new IllegalStateException("Cannot invoke " + methodName + " on a background"
                    + " thread");
        }
    }

3.  mVersion++;这个就是说明数值发生了变化,在下面调用观察者的时候需要用到

4. mData = value;更新数据

5.dispatchingValue(null)更新观察者的数据、接下来我们看下dispatchingValue这个方法的源码:

void dispatchingValue(@Nullable ObserverWrapper initiator) {
        if (mDispatchingValue) {
            mDispatchInvalidated = true;
            return;
        }
        mDispatchingValue = true;
        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);
        mDispatchingValue = false;
    }

1.判断是否正在执行更新数据的操作;如果正在更新则返回

2. 接下来就是判断 initiator 这是是否为空 如果非空则只会更改当前的initiator否则更新所有的observer 

3.结束时讲mDispatchingValue设置为false

接下来我们看看considerNotify这个就是通知的具体实现了

 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;
        observer.mObserver.onChanged((T) mData);
    }

1.检查当前的observer的active 之后会检查observer的owner的状态是否可用

2.判断最后的更新数据的版本是否大于等于当前的版本

3.更新数据

接下来我们对postValue(T value)的源码进行下分析:

 protected void postValue(T value) {
        boolean postTask;
        synchronized (mDataLock) {
            postTask = mPendingData == NOT_SET;
            mPendingData = value;
        }
        if (!postTask) {
            return;
        }
        ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);
    }
  1. 定义postTask 的布尔值,判断是否要更新。
  2. 加同步锁,防止多个子线程同时调用。
  3. (postTask = mPendingData == NOT_SET;)只有在第一次调用的时候发返回true,之后都是返回false,然后到这个值更新完毕之前的一瞬间会调用mPendingData=NOT_SET,这也是为什么多次调用 postValue()只有最后一个值才有效的原因

通过ArchTaskExecutor进行数据更新数据,我们看下mPostValueRunnable这个做了什么操作

  private final Runnable mPostValueRunnable = new Runnable() {
        @SuppressWarnings("unchecked")
        @Override
        public void run() {
            Object newValue;
            synchronized (mDataLock) {
                newValue = mPendingData;
                mPendingData = NOT_SET;
            }
            setValue((T) newValue);
        }
    };
  1. 添加同步锁
  2. 数据赋值,将mPendingData设置NOT_SET;调用 setValue()更新数据

上面我们已经分析了setValue的源码 就不再说了上去翻翻看看就可以了

最后

ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);就是将子线程的数据切换到主线程进行数据更新用到了Handler的机制、就不做过多的展开了。

LiveData setValue和postValue源码解析_第1张图片 欢迎大家扫码关注,学习更多android源码方面的知识

 

你可能感兴趣的:(android)