美文网首页
LiveData源码解析

LiveData源码解析

作者: seagazer | 来源:发表于2019-12-20 18:35 被阅读0次
  • LiveData is a data holder class that can be observed within a given lifecycle.
    正如注释所说,LiveData是一个数据持有容器,并且该容器可以感知生命周期的变化,在合适的时机通知观察者数据的变更。

  • 首先定义几个名词,LifecycleOwner owner这里暂且称之为生命周期感知者,简称感知者吧,Observer<? super T> observer是外部传入的回调接口,内部会被包装成ObserverWrapper,在此称之为观察者

  • LiveData是一个抽象类,其子类常用的有MutableLiveDataMediatorLiveDataRoomTrackingLiveData。继承关系如下:
public abstract class LiveData<T> {}

// 只是开放了postValue(T value)和setValue(T value)数据操作方法
public class MutableLiveData<T> extends LiveData<T> {}

// 依赖监听其他或多个LiveData的变化
public class MediatorLiveData<T> extends MutableLiveData<T> {}

// Room Database框架,暂不分析
class RoomTrackingLiveData<T> extends LiveData<T> {}


  • 一般情况下,首先会构造一个LiveData对象,然后注册一个LifecycleOwner生命周期感知者(一般是Fragment或者Activity)和数据变化通知的回调接口,内部把回调接口包装成观察者ObserverWrapper
一般请用步骤:
    LiveData<User> liveData = new MutableLiveData();
    liveData.observe(this, new Observer<User>() {
        @Override
        public void onChanged(User user) {
            // do something with the newest data    
        }
    });

<LiveData.java>
    static final int START_VERSION = -1;
    private int mVersion;// 这个值是用于判断是否已经通知过,保证每次通知都是最新的数据值

    public LiveData(T value) {
        mData = value;
        mVersion = START_VERSION + 1;// 默认0开始,因为该构造默认已经将数据赋值
    }

    public LiveData() {
        mData = NOT_SET;
        mVersion = START_VERSION;// 默认-1开始
    }
  • 注意observe必须在主线程调用,接着看下observe方法中的实现:
    @MainThread
    public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
        // 检查是否在主线程
        assertMainThread("observe");
        // 如果当前感知者的生命周期处于Destroy状态,直接忽略
        if (owner.getLifecycle().getCurrentState() == DESTROYED) {
            // ignore
            return;
        }
        // 将感知者和回调接口包装成观察者对象,具备感知生命周期和触发外部回调的功能
        // 生命周期感知也是一种观察者模型
        LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);
        // 一种类似Map的数据结构,缓存当前观察者
        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);
    }
  • 这个LifecycleBoundObserver观察者中实现了LifecycleObserver,具备生命周期的感知能力:
    // 对生命周期变化观察者的封装
    class LifecycleBoundObserver extends ObserverWrapper implements LifecycleEventObserver {
        // 感知者
        @NonNull
        final LifecycleOwner mOwner;

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

        // 生命周期在onStart之后才会被标记为激活状态
        @Override
        boolean shouldBeActive() {
            return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);
        }

        // 生命周期状态变更回调
        @Override
        public void onStateChanged(LifecycleOwner source, Lifecycle.Event event) {
            // 如果感知者的生命周期进入destroy,则移除该观察者(同时释放了该感知者),避免内存泄漏
            if (mOwner.getLifecycle().getCurrentState() == DESTROYED) {
                removeObserver(mObserver);
                return;
            }
            // 通知状态变更(改变父类的mActive变量值),在分发通知时会用于判断
            activeStateChanged(shouldBeActive());
        }

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

        @Override
        void detachObserver() {
            // 移除生命周期监听
            mOwner.getLifecycle().removeObserver(this);
        }
    }

    private abstract class ObserverWrapper {
        final Observer<? super T> mObserver;
        boolean mActive;// 是否可见激活状态
        int mLastVersion = START_VERSION;

        ObserverWrapper(Observer<? super T> observer) {
            mObserver = observer;
        }

        abstract boolean shouldBeActive();// 是否被激活,LifecycleBoundObserver中onStart之后为true

        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;
            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);
            }
        }
    }
  • 接着,如果我们需要改变LiveData中的数据时,只需调用其setValue或者postValue方法:
    // 缓存数据对象
    private volatile Object mData;

    // setValue只能在主线程调用
    @MainThread
    protected void setValue(T value) {
        // 判断线程
        assertMainThread("setValue");
        // 标记操作数
        mVersion++;
        // 赋值数据
        mData = value;
        // 分发通知各个观察者
        dispatchingValue(null);
    }

    // 只是切换线程的作用,可以在子线程调用
    protected void postValue(T value) {
        boolean postTask;
        synchronized (mDataLock) {
            postTask = mPendingData == NOT_SET;
            // 缓存当前改变的数据
            // 在runnable中会重新标记为NOT_SET,避免并发问题
            mPendingData = value;
        }
        if (!postTask) {
            return;
        }
        // 该runnable最终还是会调用setValue
        ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);
    }

    private final Runnable mPostValueRunnable = new Runnable() {
        @Override
        public void run() {
            Object newValue;
            synchronized (mDataLock) {
                newValue = mPendingData;
                mPendingData = NOT_SET;
            }
            //noinspection unchecked
            setValue((T) newValue);
        }
    };
  • 典型的观察者模式,接下去就是通知各个观察者数据的变化了:

    @SuppressWarnings("WeakerAccess") /* synthetic access */
    void dispatchingValue(@Nullable ObserverWrapper initiator) {
        // mDispatchingValue第一次默认false
        if (mDispatchingValue) {
            mDispatchInvalidated = true;
            return;
        }
        // mDispatchingValue赋值true
        // 此时如果下一次setValue触发,上面的mDispatchInvalidated变为true,下面for循环打断退出,并且重新执行do-while循环,这样就能保证再次分发通知是最新的数据值(这几个标记的boolean变量主要也是处理并发问题)
        mDispatchingValue = true;
        do {
            mDispatchInvalidated = false;// 默认只会执行一次do-while循环
            if (initiator != null) {
                // 当一个observer从非激活到激活状态时会进入该分支
                // 该分支只会通知该observer
                considerNotify(initiator);
                initiator = null;
            } else {
                // 一般进入该分支
                for (Iterator<Map.Entry<Observer<? super T>, ObserverWrapper>> iterator =
                        mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {
                    // 遍历取出集合中的ObserverWrapper进行通知
                    considerNotify(iterator.next().getValue());
                    if (mDispatchInvalidated) {// 如果数据在遍历期间有新的变更,则后面未通知到观察者不再通知
                        break;
                    }
                }
            }
        } while (mDispatchInvalidated);
        mDispatchingValue = false;
    }

    // 通知观察者数据变化
    private void considerNotify(ObserverWrapper observer) {
        // 观察者是否处于生命周期可见状态,mActive默认为false不进行通知,但是在LifecycleObserver生命周期onStart之后会赋值true
        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.
        // 再次检查observer的生命周期是否onStart之后
        if (!observer.shouldBeActive()) {
            observer.activeStateChanged(false);
            return;
        }
        // mLastVersion默认为-1,一般mVersion在LiveData的构造方法中赋值-1
        // 另外一个构造中赋值0,在setValue中会++变为0或者1
        // 保证同一个observer对象对该次数据变化只能接收一次通知
        if (observer.mLastVersion >= mVersion) {
            // 如果version相等,表示该数据已经通知过了
            return;
        }
        // 标识该次数据变化已经通知过了
        observer.mLastVersion = mVersion;
        //noinspection unchecked
        // 回调通知
        observer.mObserver.onChanged((T) mData);
    }

    // 对于从非激活状态到激活状态,会主动请求接收通知
    private abstract class ObserverWrapper {
        ...
        
        void activeStateChanged(boolean newActive) {
            // 生命周期状态没变,忽略
            if (newActive == mActive) {
                return;
            }
            // immediately set active state, so we'd never dispatch anything to inactive
            // owner
            mActive = newActive;
            // 是否不存在激活状态的observer
            boolean wasInactive = LiveData.this.mActiveCount == 0;
            // 如果observer生命周期激活状态,激活的observer数量+1,否则-1
            LiveData.this.mActiveCount += mActive ? 1 : -1;
            // 一般情况可以忽略该判断
            if (wasInactive && mActive) {
                onActive();// 回调通知,MediatorLiveData中有实现
            }
            if (LiveData.this.mActiveCount == 0 && !mActive) {
                onInactive();// 回调通知,MediatorLiveData中有实现
            }
            // 如果从未激活到激活,会重新分发一次
            if (mActive) {
                dispatchingValue(this);
            }
        }
    }
  • 代码不多,内部就是一个典型的观察者模型,主要核心是在通知观察者的过程中引入了生命周期的感知,对于处于激活状态的observer才进行通知更新,当observer从非激活到激活状态也会收到通知。重点是在observer生命周期结束(Destroy)时,会自动释放observer的引用,从而避免了内存泄漏。

相关文章

  • Jetpack-LiveData源码解析

    LiveData源码解析 源码版本:2.4.0需会使用:Lifecycle 导航:Jetpack-Lifecycl...

  • 学习笔记LiveData

    学习下LiveData目录 如何使用 源码解析 粘性事件 1、使用 LiveData是Google的提供标准化开发...

  • LiveData 源码解析

    LiveData 源码解析 之前做过一篇关于Lifecycle的源码解析,里面分析了 生命周期拥有者如何进行生命周...

  • LiveData源码解析

    LiveData 使用最新的 androidx 的源码。 前言 LiveData 是 Android Archit...

  • LiveData源码解析

    0.前言 关于livedata的使用详情见LiveData+ViewModel+RxJava2+autoDispo...

  • LiveData源码解析

    LiveData is a data holder class that can be observed with...

  • LiveData源码解析

    LiveData官方资料Lifecycle官方资料ViewModel官方资料 本文适合对Lifecycle、Liv...

  • LiveData源码解析

    LiveData是一个抽象函数,其子类主要有两个:MutableLiveData和MediatorLiveData...

  • LiveData源码解析

    LiveData是Google发布的一个架构组件,它是一个数据持有类,并且数据可以被观察。区别于普通的被观察者,L...

  • LiveData源码解析

    掘金文章链接 基于:macOs:10.14/AS:3.4/Android build-tools:28.0.0 思...

网友评论

      本文标题:LiveData源码解析

      本文链接:https://www.haomeiwen.com/subject/fsiinctx.html