• LiveData


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

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

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

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

    来到postValue

    1. protected void postValue(T value) {
    2. boolean postTask;
    3. synchronized (mDataLock) {
    4. postTask = mPendingData == NOT_SET;
    5. mPendingData = value;
    6. }
    7. if (!postTask) {
    8. return;
    9. }
    10. ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);
    11. }

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

    volatile Object mPendingData = NOT_SET;

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

    1. private final Runnable mPostValueRunnable = new Runnable() {
    2. @SuppressWarnings("unchecked")
    3. @Override
    4. public void run() {
    5. Object newValue;
    6. synchronized (mDataLock) {
    7. newValue = mPendingData;
    8. mPendingData = NOT_SET;
    9. }
    10. setValue((T) newValue);
    11. }
    12. };

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

    1. @MainThread
    2. protected void setValue(T value) {
    3. assertMainThread("setValue");
    4. mVersion++;
    5. mData = value;
    6. dispatchingValue(null);
    7. }

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

    dispatchingValue()的核心代码

    1. do {
    2. mDispatchInvalidated = false;
    3. if (initiator != null) {
    4. considerNotify(initiator);
    5. initiator = null;
    6. } else {
    7. //遍历观察者,分别通知他们
    8. for (Iterator<Map.Entry<Observer<? super T>, ObserverWrapper>> iterator =
    9. mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {
    10. considerNotify(iterator.next().getValue());
    11. if (mDispatchInvalidated) {
    12. break;
    13. }
    14. }
    15. }
    16. } while (mDispatchInvalidated);

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

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

    构建liveData的观察者:

    1. //构建liveData的观察者,这里为什么要传一个LifecycleOwner呢,其实就是要知道LifecycleOwner 的生 //命周期,因为liveDta是在activty/fragment在活跃状态的时候才会更新值,也就是说其实liveData也观察了activity/fragment的生命周期
    2. class LifecycleBoundObserver extends ObserverWrapper implements LifecycleEventObserver {
    3. @NonNull
    4. final LifecycleOwner mOwner;
    5. //构造函数
    6. LifecycleBoundObserver(@NonNull LifecycleOwner owner, Observer<? super T> observer) {
    7. super(observer);
    8. mOwner = owner;
    9. }
    10. @Override
    11. boolean shouldBeActive() {
    12. return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED); //判断被观察者的最新状态
    13. }
    14. //观察了lifecycleOwner的生命周期状态,所以说虽然liveData是被观察者,但是它作为被观察者通样也是一个观察者
    15. @Override
    16. public void onStateChanged(@NonNull LifecycleOwner source,
    17. @NonNull Lifecycle.Event event) {
    18. //页面当前状态
    19. Lifecycle.State currentState = mOwner.getLifecycle().getCurrentState();
    20. if (currentState == DESTROYED) { //页面都没了
    21. removeObserver(mObserver);
    22. return;
    23. }
    24. Lifecycle.State prevState = null;
    25. //状态改变
    26. while (prevState != currentState) {
    27. prevState = currentState;
    28. activeStateChanged(shouldBeActive());
    29. currentState = mOwner.getLifecycle().getCurrentState();
    30. }
    31. }
    32. @Override
    33. boolean isAttachedTo(LifecycleOwner owner) {
    34. return mOwner == owner;
    35. }
    36. @Override
    37. void detachObserver() { //不用观察了
    38. mOwner.getLifecycle().removeObserver(this);
    39. }
    40. }

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

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

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

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

     ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);

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

    追踪发现一个DefaultTaskExecutor

    1. @Override
    2. public void postToMainThread(Runnable runnable) {
    3. if (mMainHandler == null) {
    4. synchronized (mLock) {
    5. if (mMainHandler == null) {
    6. mMainHandler = createAsync(Looper.getMainLooper());
    7. }
    8. }
    9. }
    10. //noinspection ConstantConditions
    11. mMainHandler.post(runnable);
    12. }

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

  • 相关阅读:
    CentOS7中安装MYSQL5.7数据库
    【数据结构】优先级队列 - 堆
    如何在 Java 中实现无向环和有向环的检测
    秋招面试!阿里、字节、美团等大厂面试我只刷这份《Java面试题》没想到还真拿下了offer!
    C#:画许多圆
    企业大数据分析的趋势是怎样
    ida调试输入不可见字符2.0
    WPF中prism模块化
    88.(前端)商品分类TreeTable的显示——前端层级数据展示
    亚商投资顾问 早餐FM/1130物流需求延续逐步恢复态势
  • 原文地址:https://blog.csdn.net/somethingstill/article/details/127907858