本文已授权我就是马云飞公众号独家发布。
说是源码分析有点,其实就是简单的根据源码梳理一遍整体的LiveData,ViewModel和Lifecycle各个部分是如何工作的,由于本人水平有限,如果文中有错误的地方,欢迎指正。
Android Architecture Components 源码分析系列文章
- Android Architecture Components 第一篇,介绍生命周期的感知。
- Android Architecture Components 第二篇,介绍ViewModel的控制。
- Android Architecture Components 第三篇,介绍LiveDate和LifeRegistry的协同操作。
这个是Android Architecture Components(简称AAC)的第三篇,之前的两篇 文章分别介绍了Lifecycle和ViewModel的生命周期,这篇主要讲的就是最开始提出的第三个问题LiveData数据的控制。
简单案例
先列举一个简单的例子,看看如何使用的
在ViewModel中有LiveData的成员变量,然后添加一个观察者。在ViewModel中
在ViewModel中就是拥有一个成员变量,加上对应的get方法,修改数据的时候直接使用setValue更新,这样就会弹出一个Toast。
使用起来并不难,但我们的目的是了解如何实现的。
案例分析
关于上文的例子,从三个部分开始分析,一是添加观察者的时候,二是生命周期的控制,三是设置数据的时候。
添加观察者
- 先判断一下LifecycleRegistry当前的状态,如果是DESTORYED的话,就直接返回。
- 之后是将LifecycleOwner和创建Observer封装到LifecycleBoundObserver中。
- 从当前的Oberver集合中查找没有传入的Observer对应的包装类,如果有则返回,没有则添加。
- LifecycleRegistry添加包装之后的LifecycleBoundObserver观察者。
- 更新下当前的包装类的状态。
这里需要理解并记住的是LifecycleBoundObserver是一个拥有真正回调Observer和LifecycleOwner的封装类。
在LifecycleRegistry中添加观察者,这个LifecycleRegistry是在Activity/Fragment中创建的成员变量。
- 确定初始时LifecycleBoundObserverd的状态,这里大部分的情况都是INITIALIZED,除非把之前的observe写在onDestory中,不过估计一般没人这么写。
- 将传入的LifecycleBoundObserver和确定的状态封装到一个statefulObserver。在这个过程中会对observer进行一定转化,将其改变成另一种LifecycleObserver,然后再使用的时候会通过反射去调到实际需要的方法。
- 将封装过的statefulObserver和传入的observer添加到当前的一个map中进行保存,如果之前已经添加过的话,就直接返回旧的,没有的话再放入,返回null。
- 判断是否可以重入,来决定是否进行同步,这里的parentState暂时先不考虑,等最后的时候再分析。
- 其中while循环的部分是为了修改刚添加进去的ObseverWithState中state的状态。
- 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方法中。先上个我自己画的图,方便理解。
这个是我自己梳理的整体的事件流程和刷新的图。根据这个图来介绍下执行的流程。
由于上面的案例是在onCreate中订阅的,那么最开始先执行的应该是addObserver,这个时候会把LifecycleRegistry的mState(下文简称RS)置为INITIALIZED。并向observerMap中添加封装过的ObserverWithState,其中的mState(下文简称OS)为INITIALIZED。不执行同步方法。
Activity启动,传递过来第一个生命周期事件ON_CREATE,通过getStateAfter计算之后的State为CREATED赋值给RS,判断状态决定执行正推计算,OS的当前值为INITIALIZED,更改LifecycleBoundObserver的active(下文简称active)值为false。OS修改为CREATED。
事件ON_START,RS为STARTED,正推计算,OS当前值为CREATED,更改active为true。OS修改为STARTED。
事件ON_RESUME,RS为RESUMED,正推计算,OS当前值为STARTED,更改active为true。OS修改为RESUMED。
事件ON_PAUSE,RS为STARTED,反推计算,OS当前值为STARTED,更改active为true。OS修改为STARTED。
事件ON_STOP,RS为CREATED,反推计算,OS当前值为CREATED,更改active为false。OS修改为CREATED。
事件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对象。
相关的类包括:
ViewModel 、
ViewModelProvider ViewModel的提供者 、
ViewModelStore 用于保存ViewModel、
HolderFragment 添加的Fragment 用于感知宿主生命周期等。
第三部分:LiveData和LifecycleRegistry的协同操作。这里使用了两个枚举对象来概括整体的生命周期,通过Event的传递来改变当前的Lifecycyle的状态,同时更新当前的Observer是否处于活动状态。个人认为整个项目中的关于Observer的三个封装类是整个项目的骨架,State和Event就是流动血液,而HandleLifecycleEvent和Sync两个方法就是整个项目的灵魂。
相关的类包括:
LiveData 数据模型 、
LifecycleOwner 生命周期持有者 、
LifecycleRegistry 用于控制生命周期 、
ObserverWithState 保存Observer和对应的状态 、
LifecycleBoundObserver 保存Observer和LifecycleOwner 、
ReflectiveGenericLifecycleObserver 反射调用的相关类。
学习收获
这不是我第一次去深入的研究系统的源码了,不过每一次看源代码真的都能带来新的收获和想法。在学习AAC的过程中,最大的收获感觉还是对AAC项目的熟悉,能够清楚的知道每一个类,每一个方法,每一个成员变量的作用,是用来做什么的,什么起作用。当我看到它们的类名就能够知道他们是做什么的,这种熟悉感,我觉得是最大的收获。其次是在研究源码过程中一些心得体会,遇到难度高的地方的时候适当的放松,真的会有助于解决问题,我这里有好几个关键点都是我下楼散步的时候想到的为什么。
最后想要说的就是对于知识的渴望程度,或者说对于知识的了解程度,我觉得这种概念适用于所有领域,以AAC这个框架为例
- 会使用,能够写代码
- 知道原理,了解源代码是什么实现的,知道每一个部分的原理,功用。
- 能够修改,在原有的基础上进行修改,使其变得更优或者更适用于自己。
目前在学习第三方框架的时候,都在遵循着三点,争取都能够达到第二层次,部分简单的项目可以实现第三层次。这好比练武功,从登堂入室,再到烂熟于心,再到推陈出新。
会用的人太多,而知道为什么的人太少。