LiveData源码浅析

首先LiveData是一个抽象类,是不能直接new一个出来的,通常是使用MutableLiveData创建一个livedata对象。MutableLiveData仅仅只是实现了LiveData,没有额外的操作。

创建及注册

val liveData = MutableLiveData("333")

//注册
liveData.observe(this,{})
liveData.observeForever {  }
    //源码
    private SafeIterableMap, ObserverWrapper> mObservers = new SafeIterableMap<>();
            
    @MainThread
    public void observe(@NonNull LifecycleOwner owner, @NonNull Observer 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;
        }
        owner.getLifecycle().addObserver(wrapper);
    }

observe()要求传入一个LifecycleOwner和Observer。

  • LifecycleOwner:用于判断生命周期,为的就是感知生命周期,在不同阶段做出不同的反应,比如在destroy的时候会直接忽略掉这个observer。
  • Observer:观察者,当数据发生变化的时候就是通过这个发送通知的

observe主要步骤:

  1. 创建LifecycleBoundObserver,LifecycleBoundObserver主要的职责是结合生命周期维护LiveData的状态
  2. 将我们创建的LifecycleBoundObserver加入到mObservers中,mObservers是一个以Observer作为key,LifecycleBoundObserver为value的SafeIterableMap,注意虽然他的名字是Safe但并不是线程安全的,这里就不展开来讲了。
  3. 将创建的LifecycleBoundObserver加入到LifecycleOwner的Lifecycle中,如果LifecycleOwner的状态发生变化,也会通知到我们的LifecycleBoundObserver中。

注意这里的existing和isAttachedTo的判断
如果这个Observer已经存在了并且owner和旧的owner不一致,就会直接抛出异常。在Activity嵌套Fragment的时候共享一个ViewModel的时候,如果你在Activity和Fragment中对同一个LiveData是通过Lambda的方式创建Observer的,那就可能会遇到这个异常,因为你通过Lambda创建的对象是同一个,你可以通过object:Observer{}的方式创建Observer对象

    @MainThread
    public void observeForever(@NonNull Observer observer) {
        assertMainThread("observeForever");
        AlwaysActiveObserver wrapper = new AlwaysActiveObserver(observer);
        ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);
        if (existing instanceof LiveData.LifecycleBoundObserver) {
            throw new IllegalArgumentException("Cannot add the same observer"
                    + " with different lifecycles");
        }
        if (existing != null) {
            return;
        }
        wrapper.activeStateChanged(true);
    }

observeForever用的是AlwaysActiveObserver,和LifecycleBoundObserver一样都是继承的ObserverWrapper,但是AlwaysActiveObserver的shouldBeActive默认返回的是true,所以消息的通知是不受生命周期影响的,也就是说无论在处于什么状态,都会收到通知。而且在你调用observeForever的时候,LiveData的状态就直接设置成了true(mActive = true)

//注销
liveData.removeObserver {  }
liveData.removeObservers(this)

注销这块没有太多逻辑主要就两点:

  1. 从map中移除Observer
  2. 调用被移除的Observer的detachObserver方法并且把状态置为false(mActive = false)

更新value

postValue

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

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

子线程中更新数据,原理就是向主线程发送一个runable,在消息处理到这个runable的时候再进行setValue操作
注意:这里有一个同步锁synchronized,锁的对象是mDataLock,。这里有一个postTask,只有当mPendingData == NOT_SET的时候,也就是没有被赋值的时候才会发送我们的runable,否则直接就return了那么问题来了,为什么只能发送一次runable???????原因就是在handler消息处理时,在获取到Message的时候,如果message.isInUse()==true的时候会直接抛异常(throw new IllegalStateException(msg + " This message is already in use.")),而我们的mPostValueRunnable对象是一个全局变量,所以得等到这个runable处理完成才能发送,你也会发现mPostValueRunnable的run方法里将mPendingData置为了NOT_SET。虽然消息只会发送一次,但是,value赋值给mPendingData这个操作是一直在发生的,所以mPostValueRunnable的run方法中取到的mPendingData只有最新的那一个,因为mPendingData是被volatile修饰的,所以他的变化在其他线程中是立马可见的。结论就是连续调用postValue,在observer中只会拿到最后的那一个

seValue

    @MainThread
    protected void setValue(T value) {
        assertMainThread("setValue");
        mVersion++;
        mData = value;
        dispatchingValue(null);
    }
    
    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;
    }

setValue没什么特别的,直接赋值然后调用dispatchingValue,这个mVersion嘛就是分发的时候做校验用的了。
setValue进行的分发是进入②里面,直接就是进入迭代器mObservers进行分发,considerNotify()方法会校验他的version、observice的mActive状态以及observer.shouldBeActive()状态。如果是生命周期发生变化进行的分发initiator!=null,则会进入①中。

  • 那么问题来了mDispatchingValue和mDispatchInvalidated的含义是什么?????我对他的理解是:
    在并发的情况下,如果在A线程中正在进行②中的迭代并且还没结束,这时候B线程调用到了dispatchingValue方法,但是这时mDispatchingValue已经是true了(A线程把这个值改为了true),那么会将mDispatchInvalidated变为true然后return,这样B线程是不会进入到后面的循环迭代中的,这时的mDispatchInvalidated已经变成了true,那么在A线程中的迭代在遇到mDispatchInvalidated==true时会退出迭代(break,中断数据的分发),在while时因为mDispatchInvalidated == true则会重新做一遍do里面的操作,也就是重新进入②中的迭代,这样观察者拿到的都会是最新的数据,防止出现重复分发或者分发错误的情况。

  • 那么问题又来了,既然是为了解决并发那么mDispatchInvalidated和mDispatchingValue不用volatile修饰话,线程能立马感知到吗???
    对于这个问题我也不理解

以上均是个人理解,若有问题请指出哦~

ObserverWrapper

    private abstract class ObserverWrapper {
        final Observer mObserver;
        boolean mActive;
        int mLastVersion = START_VERSION;

        ObserverWrapper(Observer observer) {
            mObserver = observer;
        }

        abstract boolean shouldBeActive();

        boolean isAttachedTo(LifecycleOwner owner) {
            return false;
        }

        void detachObserver() {
        }

        void activeStateChanged(boolean newActive) {
            if (newActive == mActive) {
                return;
            }
            // immediately set active state, so we'd never dispatch anything to inactive
            // owner
            mActive = newActive;
            changeActiveCounter(mActive ? 1 : -1);
            if (mActive) {
                dispatchingValue(this);
            }
        }
    }

ObserverWrapper是LivaData的内部类,他其实是对observer做了一层包装,加入了version和active属性。在activeStateChanged方法中会改变active的状态,如果active==true就会调用dispatchingValue分发数据,在开发中遇到的数据倒灌问题就是因为在生命周期发生变化的时候调用了activeStateChanged(true),导致发送了数据

LifecycleBoundObserver

LifecycleBoundObserver是ObserverWrapper的实现类,当我们调用liveData.observer的时候内部为我们的observer创建了一个LifecycleBoundObserver,并帮我们注册在LivecyclerOwner里,当LivecyclerOwner生命周期发生变化是就会调用到LifecycleBoundObserver的onStateChanged方法

    class LifecycleBoundObserver extends ObserverWrapper implements LifecycleEventObserver {
        @NonNull
        final LifecycleOwner mOwner;

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

        @Override
        boolean shouldBeActive() {
            return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);
        }

        @Override
        public 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();
            }
        }

        @Override
        boolean isAttachedTo(LifecycleOwner owner) {
            return mOwner == owner;
        }

        @Override
        void detachObserver() {
            mOwner.getLifecycle().removeObserver(this);
        }
    }

shouldBeActive是用来判断是否可以发送通知的,由此可见只有在生命周期大于等于STARTED的时候才是可用的。onStateChanged是当生命周期发生变化的时候会调用,在这里不断的去校验Lifecycle的状态并且调用activeStateChanged方法改变liveData的状态,直到Lifecycle的状态稳定

你可能感兴趣的:(LiveData源码浅析)