LiveDate和LifeRegistry的协同操作

前言

这个是Android Architecture Components(简称AAC)的第三篇,之前的两篇 文章分别介绍了Lifecycle和ViewModel的生命周期,这篇主要讲的就是最开始提出的第三个问题LiveData数据的控制。

简单案例

先列举一个简单的例子,看看如何使用的:

在ViewModel中有LiveData的成员变量,然后添加一个观察者。在ViewModel中

在ViewModel中就是拥有一个成员变量,加上对应的get方法,修改数据的时候直接使用setValue更新,这样就会弹出一个Toast。

使用起来并不难,但我们的目的是了解如何实现的。

案例分析

关于上文的例子,从三个部分开始分析,一是添加观察者的时候,二是生命周期的控制,三是设置数据的时候。

添加观察者

  1. 先判断一下LifecycleRegistry当前的状态,如果是DESTORYED的话,就直接返回。
  2. 之后是将LifecycleOwner和创建Observer封装到LifecycleBoundObserver中。
  3. 从当前的Oberver集合中查找没有传入的Observer对应的包装类,如果有则返回,没有则添加。
  4. LifecycleRegistry添加包装之后的LifecycleBoundObserver观察者。
  5. 更新下当前的包装类的状态。

这里需要理解并记住的是LifecycleBoundObserver是一个拥有真正回调Observer和LifecycleOwner的封装类。

在LifecycleRegistry中添加观察者,这个LifecycleRegistry是在Activity/Fragment中创建的成员变量。

  1. 确定初始时LifecycleBoundObserverd的状态,这里大部分的情况都是INITIALIZED,除非把之前的observe写在onDestory中,不过估计一般没人这么写。
  2. 将传入的LifecycleBoundObserver和确定的状态封装到一个statefulObserver。在这个过程中会对observer进行一定转化,将其改变成另一种LifecycleObserver,然后再使用的时候会通过反射去调到实际需要的方法。
  3. 将封装过的statefulObserver和传入的observer添加到当前的一个map中进行保存,如果之前已经添加过的话,就直接返回旧的,没有的话再放入,返回null。
  4. 判断是否可以重入,来决定是否进行同步,这里的parentState暂时先不考虑,等最后的时候再分析。
  5. 其中while循环的部分是为了修改刚添加进去的ObseverWithState中state的状态。
  6. sync方法是事件传递的关键,在之后也会用到,就先不分析。

接下来看一下当生命周期变化的时候会发生什么?

生命周期改变

根据第一篇文章中我们可以知道当应用的生命周期变化的时候,会发送对应的生命周期事件到LifecycleRegistry的handleLifecycleEvent方法中进行处理,这里先简单的分析下逻辑。

首先设置当前的LifecycleRegistry中的mState值,之后执行sync方法

这里先判断一下是否可以进行同步,判断的条件是当前map中的oberver数量和状态,之后会根据当前的mObserverMap中保存的observer的状态和当前的Registry的状态进行比较,来决定是进行正推计算还是反推计算。先以正推计算为例:

把当前的mObserverMap中的数据进行迭代,判断状态之后执行observer.dispatchEvent()方法,来同步Observer

这里会先设置当前的Observer的状态,之后会调用Observer的onStateChanged方法,这个方法会经过一系列的变化,通过反射,最终调到LiveData中的LifecycleBoundObserver的onStateChage()方法

这两个方法最主要的作用就是判断当前的LifecycleOwner是否是active状态。如果是active状态的话就刷新数据。

数据更新

上面正好讲到刷新数据,我们来继续说一下当setvalue的时候发生了什么:

可以看到将成员变量mData赋值 ,之后也是调用了相同的dispatchingValue方法

这里的关键函数就是considerNotify,如果是通过setValue方法进行更新的话,会更新所有的observer,如果是通过handleLifecycleEvent方法进行更新的话,那么只会更改当前的observer。

首先会先检查当前的observer的active,之后会检查observer的owner的状态是否是可用的,再判断当前的版本。最后进行更新数据。

小结

到这里其实整体的生命周期事件的观察和传递,同步和更新,修改数据,都已经简单的介绍完毕了,单单拿出来一个部分其实并不难理解,主要需要明白并记住的就是LifecycleRigestry的mState、Event、ObserverWithState的mState和LifecycleBoundObserver的active。事件的来源只有一种就是handleLifecycleEvent,最终的目的地就是为了修改ObserverWithState的mState和LifecycleBoundObserver的active。

整体流程分析

每一个小部分的功能都有所了解的之后,让我们尝试下梳理最上面的案例中整个事件的传递。这里添加订阅者是在onCreate方法中。先上个我自己画的图,方便理解。

这个是我自己梳理的整体的事件流程和刷新的图。根据这个图来介绍下执行的流程。

  1. 由于上面的案例是在onCreate中订阅的,那么最开始先执行的应该是addObserver,这个时候会把LifecycleRegistry的mState(下文简称RS)置为INITIALIZED。并向observerMap中添加封装过的ObserverWithState,其中的mState(下文简称OS)为INITIALIZED。不执行同步方法。
  2. Activity启动,传递过来第一个生命周期事件ON_CREATE,通过getStateAfter计算之后的State为CREATED赋值给RS,判断状态决定执行正推计算,OS的当前值为INITIALIZED,更改LifecycleBoundObserver的active(下文简称active)值为false。OS修改为CREATED。
  3. 事件ON_START,RS为STARTED,正推计算,OS当前值为CREATED,更改active为true。OS修改为STARTED。
  4. 事件ON_RESUME,RS为RESUMED,正推计算,OS当前值为STARTED,更改active为true。OS修改为RESUMED。
  5. 事件ON_PAUSE,RS为STARTED,反推计算,OS当前值为STARTED,更改active为true。OS修改为STARTED。
  6. 事件ON_STOP,RS为CREATED,反推计算,OS当前值为CREATED,更改active为false。OS修改为CREATED。
  7. 事件ON_DESTROY,RS为DESTROYED,反推计算,OS当前值为DESTROYED,更改active为false。OS修改为DESTROYED。

整体事件流程就是这样,通过感知Activity/Fragment的生命周期,然后分发到LifecycleRegistry中进行处理,根据当前的状态来修改保存的ObserverWithState的mState,然后修改LifecycleBoundObserver的active决定数据是否可以更新。

上面的状态都是作者根据最开始的案例断点调试得出的结论,值得注意的就是因为有Application也就是ProcessLifecycleOwner的干扰,调试的时候要区分好LifeRegistry,第二个注意的就是mState的值,因为有两个mState,经常会需要进行比较,来决定同步。

总结

至此,整个Android Architecture Components架构中所有的源码都过了一遍了, 主要的难点就是在handleLifecycleEvent()和Sync()两个方法。总体的分析下整个架构:

个人认为主要分为三个部分:

第一部分:生命周期的感知包括系统生命周期的感知。其中有使用的类和技巧有,通过注册ContenProvider进行项目的初始化,通过添加Fragment来获取宿主的生命周期。通过给Application和Activity添加生命周期的回调,来进行Fragment的初始化和生命周期的感知。

相关的类包括: LifecycleRuntimeTrojanProvider 用于进行初始化init操作LifecycleDispatcher 用于进行生命周期分发处理ProcessLifecycleOwner 应用生命周期控制 ,、 ReportFragment 添加的Fragment 用于感知宿主生命周期

第二部分:ViewModel生命周期的控制。同样使用了添加Fragment来感知宿主的生命周期,通过一个HoldFragment来持有一个ViewModelStore保存当前宿主的所有ViewModel,通过工厂模式反射获得ViewModel对象。

相关的类包括: ViewModelViewModelProvider ViewModel的提供者ViewModelStore 用于保存ViewModelHolderFragment 添加的Fragment 用于感知宿主生命周期等。

第三部分:LiveData和LifecycleRegistry的协同操作。这里使用了两个枚举对象来概括整体的生命周期,通过Event的传递来改变当前的Lifecycyle的状态,同时更新当前的Observer是否处于活动状态。个人认为整个项目中的关于Observer的三个封装类是整个项目的骨架,State和Event就是流动血液,而HandleLifecycleEvent和Sync两个方法就是整个项目的灵魂。

相关的类包括: LiveData 数据模型LifecycleOwner 生命周期持有者LifecycleRegistry 用于控制生命周期ObserverWithState 保存Observer和对应的状态LifecycleBoundObserver 保存Observer和LifecycleOwnerReflectiveGenericLifecycleObserver 反射调用的相关类

学习收获

这不是我第一次去深入的研究系统的源码了,不过每一次看源代码真的都能带来新的收获和想法。在学习AAC的过程中,最大的收获感觉还是对AAC项目的熟悉,能够清楚的知道每一个类,每一个方法,每一个成员变量的作用,是用来做什么的,什么起作用。当我看到它们的类名就能够知道他们是做什么的,这种熟悉感,我觉得是最大的收获。其次是在研究源码过程中一些心得体会,遇到难度高的地方的时候适当的放松,真的会有助于解决问题,我这里有好几个关键点都是我下楼散步的时候想到的为什么。

最后想要说的就是对于知识的渴望程度,或者说对于知识的了解程度,我觉得这种概念适用于所有领域,以AAC这个框架为例

  1. 会使用,能够写代码
  2. 知道原理,了解源代码是什么实现的,知道每一个部分的原理,功用。
  3. 能够修改,在原有的基础上进行修改,使其变得更优或者更适用于自己。

目前在学习第三方框架的时候,都在遵循着三点,争取都能够达到第二层次,部分简单的项目可以实现第三层次。这好比练武功,从登堂入室,再到烂熟于心,再到推陈出新。

原文发布于微信公众号 - 我就是马云飞(coding_ma)

原文发表时间:2017-10-12

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏企鹅号快讯

一次垃圾邮件的分析

本篇文章来自同事对一次垃圾邮件的分析: 上周一(12月4号),朋友给我转发了一封垃圾邮件,邮件里面附带一个word文档,我们俩都是搞信安,自然察觉一丝危险的气味...

24570
来自专栏沈唁志

硬盘中出现eula.1028.txt等垃圾文件的原因及是否可删

1.1K20
来自专栏Play & Scala 技术分享

PlayScala 2.5.x - 实现完全异步非阻塞的流数据导出

30040
来自专栏猿人谷

多核环境下cache line的测试

前阵子接触到一道关于数组内部链表(多用于内存池技术)的数据结构的题, 这种数据结构能够比普通链表在cache中更容易命中, 理由很简单, 就是因为其在地址上是连...

27090
来自专栏非著名程序员

Android进阶:Android内存管理之道

对于移动应用开发,不管是Android还是IOS,内存都是永远的痛。但是合理的编写代码,会避免OOM的出现。 相信一步步走过来的Android从业者,每个人都...

27190
来自专栏沈唁志

【收藏】Python 爬虫的工具列表大全

26240
来自专栏VMCloud

【解析向】腾讯云的Windows Server日志配置收集工具是个什么鬼?(3)

回顾上篇,解释了场景“2”中的四个标签,也介绍了对应着Windows Server中的四个功能在日常运维中究竟起到什么作用以及如何去驾驭他们。

560130
来自专栏前端大白专栏

基于mpvue开发微信小程序(项目已开源)

31360
来自专栏我的翻译

O API - REST APIs的替代品

过去,当接到为一个网站构建一套API的任务时,我会定义一组URL来处理想要完成的各种任务。

832180
来自专栏大数据文摘

维基百科中的数据科学:手把手教你用Python读懂全球最大百科全书

几年前谁能想到,匿名贡献者们的义务工作竟创造出前所未有的巨大在线知识库?维基百科不仅是你写大学论文时最好的信息渠道,也是一个极其丰富的数据源。

17330

扫码关注云+社区

领取腾讯云代金券