我是靠谱客的博主 重要斑马,最近开发中收集的这篇文章主要介绍Jetpack-LiveData用法与源码分析LiveData定义和作用LiveData用法LiveData源码分析,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

LiveData用法与源码分析

  • LiveData定义和作用
  • LiveData用法
  • LiveData源码分析
    • Observe
    • setValue和postValue
    • 总结
    • 数据粘性(倒灌)分析

LiveData定义和作用

LiveData是一种可观察的数据存储器类。
LiveData 具有生命周期感知能力,意指它遵循其他应用组件(如 Activity、Fragment 或 Service)的生命周期。
这种感知能力可确保 LiveData 仅更新处于活跃生命周期状态的应用组件观察者。

LiveData用法

一般地,LiveData会与ViewModel等Jetpack全家桶一起配合使用,这里只分析LiveData,就直接单独使用LiveData了。创建一个单例类,其中只有一个LiveData对象

object TestLiveData {

    val mData: MutableLiveData<String> by lazy { MutableLiveData() }

}
class LiveDataActivity : AppCompatActivity() {

    private val TAG = "LiveDataActivity"

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_live_data)

        TestLiveData.mData?.observe(this, object : Observer<String> {
            override fun onChanged(t: String?) {
                Log.d(TAG, "t : $t")
            }
        })

        TestLiveData.mData?.value = "old"

        thread {
            Thread.sleep(3000)
            TestLiveData.mData?.postValue("new")
        }
    }
}

主线程使用setValue,子线程使用postValue来修改LiveData的值,最终onChanged回调必在主线程执行。页面没在展示状态,不会回调onChanged,只有在前台时,才会回调。

LiveData源码分析

Observe

首先我们先看一下observe方法具体做了哪些事情

    @MainThread
    public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
        //首先判断了是否在主线程,非主线程直接抛出异常
        assertMainThread("observe");
        //通过LifecycleOwner获取Lifecycle对象然后获取Lifecycle 的State,
        //如果是DESTROYED直接 return 了。忽略这次订阅
        if (owner.getLifecycle().getCurrentState() == DESTROYED) {
            // ignore
            return;
        }
        //把LifecycleOwner和Observer包装成LifecycleBoundObserver
        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 lifecycle");
        }
        if (existing != null) {
            return;
        }
        //形成订阅关系
        owner.getLifecycle().addObserver(wrapper);
    }

可以看到,被观察者即Activity/Fragment和观察者LifecycleBoundObserver之间已经建立了订阅关系,LifecycleBoundObserver我们后面再来分析。观察者的回调方法在何时执行,我们继续看后面的流程。

setValue和postValue

        TestLiveData.mData?.value = "old"

        thread {
            Thread.sleep(3000)
            TestLiveData.mData?.postValue("new")
        }

setValuepostValue分别调用了MutableLiveData中的setValuepostValue方法,MutableLiveData是LiveData的子类,里面只有这两个方法,这样的设计给用户提供了最简洁的调用方法,用户不需要了解复杂的LiveData类。我们继续跟进到父类中查看他们的具体实现。首先查看setValue方法

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

调用了dispatchingValue方法,参数传递的是null,继续跟代码

    void dispatchingValue(@Nullable ObserverWrapper initiator) {
        ...
        do {
            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);
        mDispatchingValue = false;
    }

不管如何判断,都是调用了considerNotify(),由于我们传入的是null,这里进入else,从我们订阅方法保存的mObservers中取出我们的观察者。我们先跟进一下considerNotify()方法

    private void considerNotify(ObserverWrapper observer) {
        if (!observer.mActive) {
            return;
        }
        if (!observer.shouldBeActive()) {
            observer.activeStateChanged(false);
            return;
        }
        if (observer.mLastVersion >= mVersion) {
            return;
        }
        observer.mLastVersion = mVersion;
        observer.mObserver.onChanged((T) mData);
    }

这里判断了mActive状态,这个值就是Lifecycle中的状态,具体可以查看我上一篇Lifecycle的文章。
最终调用了observer.mObserver.onChanged((T) mData)方法,这个observer.mObserver
就是我们的Observer接口,然后调用它的onChanged方法。到现在整个被观察者数据更新通知观察者这个流程就通了。接着我们再来看一下postValue方法

    protected void postValue(T value) {
        ...
        ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);
    }

我们可以看到,postValue方法最后,调用了postToMainThread方法,其实是切换到主线程去执行。具体如何实现的呢,我们继续跟进一下postToMainThread方法

    @Override
    public void postToMainThread(Runnable runnable) {
        if (mMainHandler == null) {
            synchronized (mLock) {
                if (mMainHandler == null) {
                    mMainHandler = createAsync(Looper.getMainLooper());
                }
            }
        }
        //noinspection ConstantConditions
        mMainHandler.post(runnable);
    }

跟进以后可以看到,最终通过拿到主线程的Looper,实例化一个handler,切换到主线程,我们来看一下runnable里看看做了哪些操作

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

看到这里一目了然了,postValue最终也是调用的setValue,后面的流程就和setValue一样了。

我们回过来再看一下LifecycleBoundObserver
LifecycleBoundObserver实现了LifecycleEventObserver接口,这个接口中有一个onStateChanged方法,被观察者生命周期变化时,会回调此方法,这也是Lifecycle中的方法,可以通过我的上一篇Lifecycle的文章中查看。

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

这里依然在判断mActive状态,当mActivetrue时,调用了dispatchingValue()方法,也就是setValue时所调用的方法,区别就是此时传入了this,这里的this也就是LifecycleBoundObserver,入参不为空,会进入if,也调用considerNotify方法,最终调用observer.mObserver.onChanged((T) mData)方法

    void dispatchingValue(@Nullable ObserverWrapper initiator) {
        ...
        do {
            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);
        mDispatchingValue = false;
    }

总结

LiveData首先提供方法,让被观察者(Activity/Fragment)与观察者(Observer)建立联系。然后再提供setValuepostValue方法,设置数据,在Lifecycle的onStateChanged方法回调时,查看mActive状态,再回调onChange()

数据粘性(倒灌)分析

一般地,在使用LiveData时,我们都会先订阅,后setValue,但如果我们先setValue,后订阅,会发现我们之前setValue的值也会回调onChange,这就是数据粘性。那么造成数据粘性的原因是什么呢,我们来通过源码分析一下。
首先我们回到setValue方法

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

如果未订阅,先调用setValue,这里mVersion默认-1,++后为0,mData保存。继续跟进dispatchingValue

    void dispatchingValue(@Nullable ObserverWrapper initiator) {
        ...
        do {
            ...
            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);
        ...
    }

前面讲过,setValue时,这个方法必进else,由于还没有订阅,mObservers中没有值,不会进入considerNotify方法。当订阅成功并生命周期改变后,回调onStateChanged,进入if,调用considerNotify方法,此时再次比较两个version

    private void considerNotify(ObserverWrapper observer) {
        ...
        if (observer.mLastVersion >= mVersion) {
            return;
        }
        observer.mLastVersion = mVersion;
        observer.mObserver.onChanged((T) mData);
    }

由于之前setValue时,mVersion已经++,所以不满足observer.mLastVersion >= mVersion,于是会回调onChange,把之前setValue时保存的mData带过去。到此就真相大白啦~

Google这样设计的本意是,当页面重建时,我们不需要再重新发起请求,而可以收到LiveData推送来的数据,但是对于我们平时开发来说大部分时候时不需要这种效果,那么我们该如何去除粘性呢?下篇文章来写吧~链接在这里

最后

以上就是重要斑马为你收集整理的Jetpack-LiveData用法与源码分析LiveData定义和作用LiveData用法LiveData源码分析的全部内容,希望文章能够帮你解决Jetpack-LiveData用法与源码分析LiveData定义和作用LiveData用法LiveData源码分析所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(41)

评论列表共有 0 条评论

立即
投稿
返回
顶部