Android JetPack深入分析LiveData源码

这篇具有很好参考价值的文章主要介绍了Android JetPack深入分析LiveData源码。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

前言

Google Android开发者 LiveData概览

在了解LiveData源码之前,建议先了解LifeCycle相关知识,请参考:Android JetPack深入分析Lifecycle源码

定义

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

从定义中,我们可以大概知道:LiveData是一个数据存储类,能够感知ActivityFragment等组件的生命周期,并且支持对它存储的数据进行观察;

使用LiveData的好处以及如何使用这里就不再过多赘述,更多查看Google官方文档;

这里就直接进入正题,源码分析LiveData是如何实现生命周期监听以及数据更新的;

绑定观察者

调用LiveData.observe()方法会进行对应观察者绑定,相关代码如下:

	  private SafeIterableMap<Observer<? super T>, ObserverWrapper> mObservers =
            new SafeIterableMap<>();
		
	//LifecycleOwner对应被观察者,Observer对应观察者
    @MainThread
    public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
    	//1.进行主线程判断,不是主线程中调用直接抛异常;
        assertMainThread("observe");
        //2.如果被观察者已销毁,则直接返回
        if (owner.getLifecycle().getCurrentState() == DESTROYED) {
            return;
        }
        //3.将观察者和被观察者包装成LifecycleBoundObserver对象
        LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);
        //4.mObservers是以Observer为key,LifecycleBoundObserver为value的,内部采用双链表结构存储,根据传入的观察者Observer查询LifecycleBoundObserver,如果没查到,则将observer, wrapper以Entry<K,V>形式插入到链表中,如果已存在,则直接返回对应的ObserverWrapper
        ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);
        //5.如果链表中已存在&&绑定的是同一个被观察者,则抛异常;
        if (existing != null && !existing.isAttachedTo(owner)) {
            throw new IllegalArgumentException("Cannot add the same observer"
                    + " with different lifecycles");
        }
        //6.如果已存在,则直接返回
        if (existing != null) {
            return;
        }
        //7.由前面的Lifecycle源码分析可知,最终将wrapper添加到LifecycleRegistry中维护的观察者集合中;
        owner.getLifecycle().addObserver(wrapper);
    }

其中LifecycleBoundObserver类相关代码如下:

	//1.实现了LifecycleEventObserver接口,而我们知道LifecycleEventObserver继承于LifecycleObserver,因此上述可以将LifecycleBoundObserver存储到LifecycleRegistry中维护的观察者集合中;
    class LifecycleBoundObserver extends ObserverWrapper implements LifecycleEventObserver {
        @NonNull
        final LifecycleOwner mOwner;

        LifecycleBoundObserver(@NonNull LifecycleOwner owner, Observer<? super T> observer) {
            super(observer);
            mOwner = owner;
        }
		//当前被观察者是否处于活跃状态,即state应该>=STARTED,对应STARTED和RESUMED两种状态
        @Override
        boolean shouldBeActive() {
            return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);
        }
		
		//Lifecycle源码分析中,分发生命周期事件的时候,会执行此onStateChanged方法
        @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);
        }
    }
	
	//内部维护了 观察者、观察者活跃标志、观察者对应版本号信息
    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();

        boolean isAttachedTo(LifecycleOwner owner) {
            return false;
        }

        void detachObserver() {
        }

        void activeStateChanged(boolean newActive) {
            if (newActive == mActive) {
                return;
            }
            mActive = newActive;
            changeActiveCounter(mActive ? 1 : -1);
            if (mActive) {
                dispatchingValue(this);
            }
        }
    }

小结

从上面源码分析,我们可以知道,LiveData绑定观察者会将观察者以及被观察者包装LifecycleBoundObserver对象【内部持有观察者被观察者观察者版本号观察者活跃标志等信息】,并在其内部维护了一个双向链表结构用于存储LifecycleBoundObserver对象,最终会将观察者添加到LifecycleRegistry维护的观察者集合中,从而实现生命周期的监听!!!

更新数据

LiveData.postValue最终调用的也是LiveData.setValue()方法,只是做了下切换到主线程,这里就直接看LiveData.setValue()方法;

public abstract class LiveData<T> {
	//当前LiveData对应的版本号
	private int mVersion;
	//当前是否正在刷新数据
    private boolean mDispatchingValue;
	//刷新标记
    private boolean mDispatchInvalidated;

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

setValue方法主要做了以下几件事:

  • 判断执行线程是否是主线程;
  • 当前版本号+1;
  • 将传入的value设置给全局变量mData;
  • 执行dispatchingValue(null)进行数据分发;

我们紧接着看下dispatchingValue(null)方法:

    void dispatchingValue(@Nullable ObserverWrapper initiator) { 
    	//1.如果正在刷新数据,标记之前的刷新数据无效,mDispatchInvalidated = true会影响正在for循环中的逻辑
        if (mDispatchingValue) {
            mDispatchInvalidated = true;
            return;
        }
        //2.设置正在刷新
        mDispatchingValue = true;
        do {
         	//3.修改刷新非法标记为false
            mDispatchInvalidated = false;
            if (initiator != null) {
            	//4.如果传入initiator,表示只通知对应的观察者更新数据
                considerNotify(initiator);
                initiator = null;
            } else {
            	//5.遍历所有观察者,调用considerNotify方法进行数据更新;
            	//这里是do-while逻辑,会先执行一遍do操作,遍历所有的观察者进行数据更新,如果在更新过程中再次调用了setValue方法
            	//则会先跳出循环,重新遍历所有观察者通知数据更新【mDispatchInvalidated为true】
                for (Iterator<Map.Entry<Observer<? super T>, ObserverWrapper>> iterator =
                        mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {
                    considerNotify(iterator.next().getValue());
                    if (mDispatchInvalidated) {
                        break;
                    }
                }
            }
        } while (mDispatchInvalidated);
        mDispatchingValue = false;
    }

dispatchingValue()方法中会判断mDispatchingValue【当前是否正在分发数据】,如果不是则遍历所有观察者进行分发,如果当前正在分发数据【setValue方法没执行完被再次调用】,则会先跳出观察者遍历,重新进行一次观察者遍历数据分发;【假设initiator传入为null】,具体数据更新由considerNotify方法完成;

    private void considerNotify(ObserverWrapper observer) {
    	  // 1.active状态检查
        if (!observer.mActive) {
            return;
        }
        //2.判断当前观察者是否处于活跃状态【被观察者生命周期状态为STARTED,RESUMED】
        if (!observer.shouldBeActive()) {
			//3.设置mActive为false,不回调onChanged方法;
            observer.activeStateChanged(false);
            return;
        }
        //3.版本比对,mLastVersion默认为-1,而mVersion默认为0,因此会导致粘性事件产生【后注册的观察者会接收到前面的数据更新操作】,如果不想粘性,这里可以通过hook修改mLastVersion和mVersion一致实现;
        if (observer.mLastVersion >= mVersion) {
            return;
        }
        //4.同步观察者版本号和LiveData版本号一致;
        observer.mLastVersion = mVersion;
        //5.回调观察者对应的onChanged方法
        observer.mObserver.onChanged((T) mData);
    }

considerNotify()方法中会进行生命周期活跃版本号判断,满足条件,最终会回调Observer.onChanged()方法!!!

更新数据流程图

Android JetPack深入分析LiveData源码,JetPack,android jetpack,android

结语

如果以上文章对您有一点点帮助,希望您不要吝啬的点个赞加个关注,您每一次小小的举动都是我坚持写作的不懈动力!ღ( ´・ᴗ・` )文章来源地址https://www.toymoban.com/news/detail-529006.html

到了这里,关于Android JetPack深入分析LiveData源码的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Android Jetpack 从使用到源码深耕【LiveData 从实践到原理 】(四)

    前面,经过LiveData的使用、自我编程实现LiveData框架、Jetpack LiveData源码探索几节的学习,相信大家都收益匪浅。 Android Jetpack 从使用到源码深耕【LiveData 从实践到原理 】(一) Android Jetpack 从使用到源码深耕【LiveData 从实践到原理 】(二) Android Jetpack 从使用到源码深耕【Li

    2024年02月04日
    浏览(42)
  • Android JetPack~LiveData(二) 数据倒灌问题

    Android数据绑定技术一,企业级开发 Android数据绑定技术二,企业级开发 Android  JetPack~ DataBinding(数据绑定)(一)    集成与使用 Android  JetPack~ LiveData (一)   介绍与使用 Android JetPack~LiveData(二) 数据倒灌问题 Android  JetPack~ ViewModel (一)   介绍与使用 如果我们在一个home页面获取网络

    2024年02月02日
    浏览(37)
  • Android-Jetpack>;>; LiveData粘性数据

    米哈游校招技术提前批来啦 靠谱内推,全程跟进! 有需要的小伙伴可以帮忙辅导简历哈! 投递后可私信我跟进~ 内推码:NE449    入职 南大通用 个人感受 Hello啊各位朋友们,这里先说一下个人情况吧,我是河北工业大学23届的本科生,计算机本专业的。然后我是春招进的南

    2024年02月17日
    浏览(62)
  • Android Jetpack组件的全方位分析

    Jetpack是一个用于简化Android应用程序开发的工具包,包含了一系列的组件和工具。Jetpack包含了很多组件,如LiveData、ViewModel、Room、Data Binding、Navigation等。 Jetpack组件是一种更高级别的抽象,它们可以提供更简洁、更易于使用的API。支持库是Jetpack组件的底层实现。 基本概念和

    2024年02月11日
    浏览(43)
  • Android Jetpack 从使用到源码深耕【ViewModel从实践到原理 】(一)

    五一期间,我们来一起学习总结一下Jetpack的ViewModel组件,从使用、源码、经验来总结分析。 Android Jetpack 从使用到源码深耕【ViewModel从实践到原理 】(一) Android Jetpack 从使用到源码深耕【ViewModel从实践到原理 】(二) Android Jetpack 从使用到源码深耕【ViewModel从实践到原理

    2024年02月01日
    浏览(51)
  • Android Jetpack 从使用到源码深耕【ViewModel从实践到原理 】(二)

    上文,我们对ViewModel的引入背景、使用、进行了实例编码、总结分析,本文开始,我们对ViewModel的实现源码,进行探索、总结。 Android Jetpack 从使用到源码深耕【ViewModel从实践到原理 】(一) Android Jetpack 从使用到源码深耕【ViewModel从实践到原理 】(二) Android Jetpack 从使用

    2024年02月04日
    浏览(51)
  • Android Jetpack 从使用到源码深耕【ViewModel从实践到原理 】(三)

    上文,我们通过简单的ViewModel使用源码入手,对其源码进行阅读,原理进行了简单总结,简单来说,ViewModel是通过Activity的onRetainNonConfigurationInstance 与 getLastNonConfigurationInstance的自动调用,实现了 ViewModel数据的存储和恢复,数据存储在ViewModelStore的map中,更加明确的话,应该是

    2024年02月04日
    浏览(129)
  • Android Jetpack 从使用到源码深耕【调度任务组件WorkManager 从实践到原理 】(三)

    本文,是Jetpack 调度任务组件WorkManager 从实践到原理系列文章的最后一篇,本文我们将对WorkManager 任务的具体执行源码,进行深入的解读。 大家坐好,我们要开始飙车了。 书接上文,我们既然知道了WorkManager,既然把worker包装为了workrequset,然后提交到了线程池执行,那么我

    2023年04月08日
    浏览(35)
  • Android Jetpack 从使用到源码深耕【调度任务组件WorkManager 从实践到原理 】(二)

    上文,我们进行了google 任务调度系列知识体系的回顾、探索,引出了WorkManager 。然后我们基于一个简单的需求背景,进行了WorkManager的引入使用,不过从使用上,我们看到和JobScheduler几乎一样的使用步骤,所以猜想内部实现原理,估计和JobScheduler差不多,本文,我们就WorkMa

    2023年04月09日
    浏览(44)
  • Android Jetpack 从使用到源码深耕【调度任务组件WorkManager 从实践到原理 】(一)

    本文,我们对Jetpack的调度任务组件WorkManager ,由使用入手,对其源码进行深入学习、总结一下。 研究这个框架之前,我们基于自己已有的知识体系,想一些问题,给自己设定一些目标,带着目标和问题,去阅读这块的源码,相信收获会更多更深一些。 1) WorkManager 是做什么

    2024年02月02日
    浏览(49)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包