JetPack系列---LiveData源码分析

最近公司项目不忙,抽时间把LiveData的源码撸了两边,每撸一次,印象就深刻几分,整体的思路就更加的清晰了,越发的觉得LiveData的源码真的很简单~

一、源码分析

注:使用的livedata和viewmodel的版本为2.2.0

我们在使用LiveData的时候,通常和ViewModel配合来使用。在ViewModel中创建LiveData对象,使用ViewModelProvider创建ViewModel,Owner对象相同,就保证了ViewModel是相同的对象,那么LiveData对象就是相同的,就可以进行数据的监听了,关于LiveData的使用,可以上官网去摸索,这里我们只撸源码。

其实LiveData也不一定非要和ViewModel配合使用,比如LiveDataBus。因为官网的示例中和ViewModel配合使用了,所以我们也正好看一下ViewModel的源码

LiveData的使用分了三步:(1)获得ViewModel对象(2)注册 (3)数据发送

源码的分析我们也从这三步来撸

1.获取ViewModel对象

MessageListViewModel viewModel = new ViewModelProvider(this).get(MessageListViewModel.class);

MessageListViewModel是我创建的ViewModel类,这里用到了ViewModelProvider的两个方法,一个构造方法,一个get方法

我们想看一下构造方法

    public ViewModelProvider(@NonNull ViewModelStoreOwner owner) {
        this(owner.getViewModelStore(), owner instanceof HasDefaultViewModelProviderFactory
                ? ((HasDefaultViewModelProviderFactory) owner).getDefaultViewModelProviderFactory()
                : NewInstanceFactory.getInstance());
    }

    public ViewModelProvider(@NonNull ViewModelStoreOwner owner, @NonNull Factory factory) {
        this(owner.getViewModelStore(), factory);
    }

    public ViewModelProvider(@NonNull ViewModelStore store, @NonNull Factory factory) {
        mFactory = factory;
        mViewModelStore = store;
    }

构造方法比较简单,主要对mFactory和mViewModelStore对象进行了初始化赋值。

mFactory:工厂类,从名字上我们可以猜测出主要是用来进行创建对象,所创建的对象正是ViewModel对象,这里mFactory正是通过NewInstanceFactory.getInstance赋值的

mViewModelStore:存储类,从名字上我们也可以猜出,主要是用key来存储ViewModel的,ViewModelStore的内部就是一个HashMap,同学们可以自己点击去看看,很简单。

mViewModelStore是owner的调用getViewModelStore来获取的,我这里的owner其实就是Activity对象,而Activity的父类是ComponentActivity,也就是说ComponentActivity实现了getViewModelStore方法,创建了mViewModelStore对象。自己点进源码看吧,超简单的,就是对mViewModel进行了创建

我们再看一下get方法

    private static final String DEFAULT_KEY = "androidx.lifecycle.ViewModelProvider.DefaultKey";    
    @NonNull
    @MainThread
    public <T extends ViewModel> T get(@NonNull Class<T> modelClass) {
        String canonicalName = modelClass.getCanonicalName();
        if (canonicalName == null) {
            throw new IllegalArgumentException("Local and anonymous classes can not be ViewModels");
        }
        return get(DEFAULT_KEY + ":" + canonicalName, modelClass);
    }

    @NonNull
    @MainThread
    public <T extends ViewModel> T get(@NonNull String key, @NonNull Class<T> modelClass) {
        ViewModel viewModel = mViewModelStore.get(key);

        if (modelClass.isInstance(viewModel)) {
            if (mFactory instanceof OnRequeryFactory) {
                ((OnRequeryFactory) mFactory).onRequery(viewModel);
            }
            return (T) viewModel;
        } else {
            //noinspection StatementWithEmptyBody
            if (viewModel != null) {
                // TODO: log a warning.
            }
        }
        if (mFactory instanceof KeyedFactory) {
            viewModel = ((KeyedFactory) (mFactory)).create(key, modelClass);
        } else {
            viewModel = (mFactory).create(modelClass);
        }
        mViewModelStore.put(key, viewModel);
        return (T) viewModel;
    }

首先modelClass通过getCanonicalName方法拿到了ViewModel的全类名,然后和DEFAULT_KEY组成了一个新key,从mViewModelStore中进行查找,是否已经有此类了。如果有并且不为空,则返回此对象;否则,我们通过mFactory的create方法进行ViewModel对象的创建,而这个mFactory是NewInstanceFactory,所以我们看一下NewInstanceFactory中的create方法

        @NonNull
        @Override
        public <T extends ViewModel> T create(@NonNull Class<T> modelClass) {
            //noinspection TryWithIdenticalCatches
            try {
                return modelClass.newInstance();
            } catch (InstantiationException e) {
                throw new RuntimeException("Cannot create an instance of " + modelClass, e);
            } catch (IllegalAccessException e) {
                throw new RuntimeException("Cannot create an instance of " + modelClass, e);
            }
        }

使用了newInstance创建了ViewModel的对象

ViewModel对象的获取就这些东西,so easy~

2.注册(observer方法)

viewModel.userPagedList.observe(this, new Observer<MessageListBean.DataBean>() {
            @Override
            public void onChanged(MessageListBean.DataBean dataBean) {
                
            }
        });

userPagedList是我在ViewModel中创建的LiveData对象,MessageListBean.DataBean是被监听的数据。我们直接进入LiveData中的observe方法

    @MainThread
    public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> 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);
    }

如果当前owner的状态时销毁状态,那么直接阻断返回

我们看到LifecycleBoundObserver这个类,从这个类的命名wrapper上可以看出来,LifecycleBoundObserver这个类其实就是一个包装类,它接收了owner和observer两个参数,我们进入查看一下它的源码

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) {
            if (mOwner.getLifecycle().getCurrentState() == DESTROYED) {
                removeObserver(mObserver);
                return;
            }
            activeStateChanged(shouldBeActive());
        }

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

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

接口LifecycleEventObserver:这个类只有一个待实现方法onStateChanged。很明显,从名字上我们就可以猜测是owner生命周期变化时,会执行这个方法

父类ObserverWrapper:防止内容太乱,这个类我就不贴出来了,就在LifecycleBoundObserver的下面。内容不多,很易懂。我们上面实现的Observer类方法就会保存在这里。这个类中还有一个mActive属性,当它变为true的时候,表示owner处于活跃状态,那么就会通过这个类进行事件的分发,执行Observer的onChange方法。其中还有一个mLastVersion需要注意,这是一个标识,LiveData类中有一个mVersion属性,数据每发送一次,mVersion就会进行加1。如果mVersion比mLastVersion大,才会执行onChange方法。所以想要改变LiveData类似于粘性的特征,可以从这个mLastVersion属性入手,hook进行改变

LifecycleBoundObserver:owner会被保存在这里,owner的状态的变化会在这里获取到,从而传递给父类ObserverWrapper进行事件的分发。如果owner的状态变为不活跃是,Observer的移除也是在这里

我们回到LiveData的observer方法中,可以看到:observer为键,wrapper为值,存到了mObservers这个map中,随后进行addObserver进行了绑定。

mObservers这个类是一个map,当事件被触发需要进行发送的时候,就是遍历这个类,进行onChange

本来想画一张流程图的,但是这个流程简单到我不想画...

3.数据发送(setValue方法)

postValue方法我不去过多的描述,和setValue的区别就是线程调度,最终还是会回到setValue方法中来,我们看一下setValue方法

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

mVersion属性进行了加1,mData复制为要发送的value值,然后执行dispatchingValue方法,我们看下这个方法:

    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<Map.Entry<Observer<? super T>, ObserverWrapper>> iterator =
                        mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {
                    considerNotify(iterator.next().getValue());
                    if (mDispatchInvalidated) {
                        break;
                    }
                }
            }
        } while (mDispatchInvalidated);
        mDispatchingValue = false;
    }

因为形参initiator是null,所以对mObservers执行了遍历,mObservers的value是ObserverWrapper,随后调用了considerNotify方法,我们看下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);
    }

首先进行了owner状态的判断(上面简单的描述过),之后进行了version的比较(这个上面也说过),随后执行了onChange方法,到此结束。

整个事件分发的过程就是这么简单。但是还没有结束,还有很多问题我们都没有进行描述,我们继续往下看

二、问题

1.LiveData是如何与Activity和Fragment进行生命周期绑定的?

我们以Activity为例。其实上面也简单说过,Activity生命周期的变化会通过调用LifecycleEventObserver接口的onStateChanged方法通知到LifecycleBoundObserver,具体的流程是怎么样的呢?我们先用语言简单描述一下,再通过流程图来理解

所有的一切都是从LifecycleRegistry开始的,无论是Activity,还是Fragment都有LifecycleRegistry对象的创建,从名称上我们知道,这个是生命周期的一个注册器。Activity的生命周期的改变,会调用到LifecycleRegistry的handleLifecycleEvent方法(整个过程我是倒着找到,所以能找到这个方法),而Activity的生命周期的变化通知是父类FragmentActivity中进行的,点击handleLifecycleEvent方法就可以发现,上图

2.如果ActivityA中对一个事件进行了监听,ActivityB中也进行了此事件的监听,在ActivityA中对事件进行setValue,此时如果跳转到ActivityB中,为什么也能收到相应事件的改变?(类似粘性)

估计用过LiveData的同学都知道上述的问题,那是什么原因导致LiveData在进行事件传递的时候有这种粘性特征呢?

如果理解了上述流程图的话,估计这个问题就已经明白了。因为每次生命周期的改变都会执行onChange方法,如果你在Activity的onCreate方法中注册,那么当Activity变为活跃状态时,就会执行onChage方法,从而实现了类似于粘性特征的功能。如果不想使用这种粘性特征怎么办?上面我提到过,通过hook的方式来改变mLastVersion的值,具体的办法可以百度一下,有很多的~

3.LiveData中,在执行onChange方法前,为什么要做mVersion的比较?它的作用是什么?

因为Activity每次进行生命周期改变的时候,都会执行onChange方法,而mVersion执行在发送数据的时候才会加1。通过mVersion的比较,可以防止生命周期变化时,多次执行onChange方法

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值