Android Jetpack架构组件——LiveData原理篇

Posted 我就是马云飞

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android Jetpack架构组件——LiveData原理篇相关的知识,希望对你有一定的参考价值。

前言

前面我们讲到了LiveData是如何使用的,并在最后留了几个问题。比如它是如何通过生命周期去变化的?为什么DESTORY不会接受数据?postValue和setValue是如何更新数据的?Transformations的map和switchMap方法内部是如何操作的?别急,本篇文章会带你了解其原理。接下来上正文。

LiveData是如何观察生命周期变化的?

如何观察生命周期,我们需要通过他的observe方法去看,我们上源码:

    @MainThread
    public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) 
        assertMainThread("observe");
        //1
        if (owner.getLifecycle().getCurrentState() == DESTROYED) 
            // ignore
            return;
        
        //2
        LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);
        //3
        ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);
        //4
        if (existing != null && !existing.isAttachedTo(owner)) 
            throw new IllegalArgumentException("Cannot add the same observer"
                    + " with different lifecycles");
        
        if (existing != null) 
            return;
        
        //5
        owner.getLifecycle().addObserver(wrapper);
    

我在源码加了几个注释,我们一个个看。

注释一:可以看出通过当前组件的LifecycleOwner拿到生命周期的状态,如果是DESTORY就返回,不做任何处理。

注释二:新建了一个LifecycleBoundObserver包装类,并把owner和observer丢进去。

注释三:将observer和wrapper做一个存储。我们看下putIfAbsent方法:

public V putIfAbsent(@NonNull K key, @NonNull V v) 
        Entry<K, V> entry = get(key);
        if (entry != null) 
            return entry.mValue;
        
        put(key, v);
        return null;
    

可以看出,如何这个entry存在的话,不像正常map做替换,而且直接拿到对应的value。不存在的话正常put操作。

注释四:判断这个owner是否存在,如何存在就抛出异常,提示无法添加具有不同生命周期的同一观察者。

注释五:将LifecycleBoundObserver添加到Lifecycle中完成注册,所以我们LiveData的生命周期观察其实来源于LifecycleOwner,这也就是为什么LiveData具备了观察组件生命周期变化的能力。

observe是如何同步数据的?

上面代码中我们知道有一个LifecycleBoundObserver的包装类。我们看看其实现逻辑:

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

        LifecycleBoundObserver(@NonNull LifecycleOwner owner, Observer<? super T> 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);
        
    

我们来关注几个方法。通过ObserverWrapper实现了shouldBeActive。从命名上可以看出判读是否活跃。从代码看来也就是STARTED和RESUMED。

在看另一个,通过LifecycleEventObserver实现了onStateChanged方法。我们可以看到如果当前的STATE是DESTROYED时会移除观察者监听。接着通过判读状态是否匹配调用了activeStateChanged方法。因为prevState定义为null。所以此方法最少执行一次。那么我们看看它是如何处理的。

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);
            
        

可以看到它会先调用changeActiveCounter,字面意思也就是改变活跃的数量。

@MainThread
    void changeActiveCounter(int change) 
        int previousActiveCount = mActiveCount;
        mActiveCount += change;
        if (mChangingActiveState) 
            return;
        
        mChangingActiveState = true;
        try 
            while (previousActiveCount != mActiveCount) 
                boolean needToCallActive = previousActiveCount == 0 && mActiveCount > 0;
                boolean needToCallInactive = previousActiveCount > 0 && mActiveCount == 0;
                previousActiveCount = mActiveCount;
                if (needToCallActive) 
                    onActive();
                 else if (needToCallInactive) 
                    onInactive();
                
            
         finally 
            mChangingActiveState = false;
        
    

从逻辑上我们可以看出previousActiveCount默认为0,mActiveCount可能为1,可能为-1,mChangingActiveState默认为flase。也就是一定会走进while循环里面去。从里面代码可以看出需要通知组件存活状态就调用onActive,需要通知组件不活跃就调用onInactive。然后我们往回看,如果组件是活跃的就会调用dispatchingValue方法。我们接着看:

    void dispatchingValue(@Nullable ObserverWrapper initiator) 
        //1
        if (mDispatchingValue) 
            //2
            mDispatchInvalidated = true;
            return;
        
        mDispatchingValue = true;
        do 
            //3
            mDispatchInvalidated = false;
            if (initiator != null) 
                considerNotify(initiator);
                initiator = null;
             else 
                for (Iterator<Map.Entry<Observer<? super T>, ObserverWrapper>> iterator =
                        mObservers.iteratorWithAdditions(); iterator.hasNext(); ) 
                    considerNotify(iterator.next().getValue());
                    if (mDispatchInvalidated) 
                        break;
                    
                
            
         while (mDispatchInvalidated);
        //4
        mDispatchingValue = false;
    

注释一中mDispatchingValue用于标记当前是否处于分发状态中,如果是存在分发状态,则执行注释二表示分发无效并直接return。注释三则将分发状态修改成有效状态。我们可以看到后面无论initiator是否为null都会执行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);
    

可以看到当前状态如果是非活跃的就直接return了。接着判读了如果当前observer对应组件的状态不是Active,就会再次调用activeStateChanged方法,并传入false,其方法内部会再次判断是否执行onActive方法和onInactive方法回调。接着就会调用Observer的onChange方法通知数据更新。

postValue和setValue的区别是什么?

我们知道虽然我们调用observe方法对数据进行观察,但是真正同步数据的代码是postValue和setValue。话不多说,上代码:

    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);
    

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

我们看到setValue加上了@MainThread注解,也就是在主线程中执行,并且会调用dispatchingValue传入null。这个前面我们有提到过。而postValue其实是在子线程操作,最后通过postToMainThread同步至主线程,最后其实还是调用了setValue方法。

Transformations分析

前面我们在使用篇时有提到Transformations有2个方法,一个是map。一个是switchMap。我们一个个的看。

map

 @MainThread
    @NonNull
    public static <X, Y> LiveData<Y> map(
            @NonNull LiveData<X> source,
            @NonNull final Function<X, Y> mapFunction) 
        final MediatorLiveData<Y> result = new MediatorLiveData<>();
        result.addSource(source, new Observer<X>() 
            @Override
            public void onChanged(@Nullable X x) 
                result.setValue(mapFunction.apply(x));
            
        );
        return result;
    

我们可以看到此处调用了MediatorLiveData的addSource方法:

    @MainThread
    public <S> void addSource(@NonNull LiveData<S> source, @NonNull Observer<? super S> onChanged) 
        Source<S> e = new Source<>(source, onChanged);
        Source<?> existing = mSources.putIfAbsent(source, e);
        if (existing != null && existing.mObserver != onChanged) 
            throw new IllegalArgumentException(
                    "This source was already added with the different observer");
        
        if (existing != null) 
            return;
        
        if (hasActiveObservers()) 
            e.plug();
        
    

可以看到最后一个判断,如果存在活跃的观察者,即调用Source的plug方法。

private static class Source<V> implements Observer<V> 
        final LiveData<V> mLiveData;
        final Observer<? super V> mObserver;
        int mVersion = START_VERSION;

        Source(LiveData<V> liveData, final Observer<? super V> observer) 
            mLiveData = liveData;
            mObserver = observer;
        

        void plug() 
            mLiveData.observeForever(this);
        

        void unplug() 
            mLiveData.removeObserver(this);
        

        @Override
        public void onChanged(@Nullable V v) 
            if (mVersion != mLiveData.getVersion()) 
                mVersion = mLiveData.getVersion();
                mObserver.onChanged(v);
            
        
    

我们可以看到Source提供了添加观察者,移除观察者,以及监听的操作。哎,不对,是不是发现哪里有点问题?这里它调用的是observeForever,而不是addObserver。那我们接着看:

    public void observeForever(@NonNull Observer<? super T> 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);
    

可以看出,这里最后其实还是调用了ObserverWrapper的activeStateChanged方法。

switchMap

    @MainThread
    @NonNull
    public static <X, Y> LiveData<Y> switchMap(
            @NonNull LiveData<X> source,
            @NonNull final Function<X, LiveData<Y>> switchMapFunction) 
        final MediatorLiveData<Y> result = new MediatorLiveData<>();
        result.addSource(source, new Observer<X>() 
            LiveData<Y> mSource;

            @Override
            public void onChanged(@Nullable X x) 
                LiveData<Y> newLiveData = switchMapFunction.apply(x);
                if (mSource == newLiveData) 
                    return;
                
                if (mSource != null) 
                    result.removeSource(mSource);
                
                mSource = newLiveData;
                if (mSource != null) 
                    result.addSource(mSource, new Observer<Y>() 
                        @Override
                        public void onChanged(@Nullable Y y) 
                            result.setValue(y);
                        
                    );
                
            
        );
        return result;
    

可以看出来,整体和map类似,只是内部包装了一层,让其返回结果是一个LiveData而已。

总结

本篇我们整体介绍了LiveData的使用原理,也就是上篇文章遗留下来的几个问题。总之,我们不仅需要知其然,还需要知其所以然。

参考

Android Jetpack架构组件(五)带你了解LiveData(原理篇)

本文首发于我的个人博客:Android Jetpack架构组件——LiveData原理篇

更多文章请关注我的公众号:码农职场

以上是关于Android Jetpack架构组件——LiveData原理篇的主要内容,如果未能解决你的问题,请参考以下文章

Android Jetpack架构组件——什么是Jetpack?

Android Jetpack架构组件——什么是Jetpack?

Android高级Jetpack架构组件+Jetpack compose强化实战

Jetpack之LiveData分析

Android Jetpack架构组件带你了解Android Jetpack

Android Jetpack架构组件(入门教程及进阶实战)独家首发