android 生命周期_Android生命周期组件 Lifecycle 源码详解(一)
在上篇文章:
warmcheng:Android生命周期组件 Lifecycle 使用详解zhuanlan.zhihu.com
中,我们讲了 Lifecycle 的简单使用,本篇我们来研究下它的源码。
基础环境搭建
首先,按照上篇文章所讲,快速搭建环境。
添加 Lifecycle 轻量级依赖库:
1 implementation "android.arch.lifecycle:runtime:1.1.1"
添加support library 28.0.0
的支持库(希望大家能先保持一致,因为不同版本的源码是有区别的,后面会将到):
1implementation 'com.android.support:appcompat-v7:28.0.0'
再添加个注解处理器相关的依赖,至于用处,后面会讲:
1annotationProcessor "android.arch.lifecycle:compiler:1.1.1"
接下来创建实现了 LifecycleObserver 接口的 MyObserver 类:
让我们的 Activity 继承自 AppCompatActivity,并在 onCreate() 方法中通过 getLifecycle().addObserver(new MyObserver())
绑定 MyObserver :
核心代码就一句,getLifecycle().addObserver(new MyObserver())
,就能让我们创建的 MyObserver 类,拥有生命周期感知能力。我们知道,这里主要的对象就两个。一个是 getLifecycle() 方法返回来的 LifecycleRegistry 对象(继承自抽象类 Lifecycle),一个是我们创建的需要监听生命周期的类 MyObserver。那我们不禁要问:LifecycleRegistry 是如何感知到生命周期的?它又是如何把生命周期事件分发给 LifecycleObserver 的?
我们先来解决第一个问题,LifecycleRegistry 是如何感知到生命周期的。
LifecycleRegistry 是如何感知到生命周期的
首先,我们Command/Ctrl + 鼠标左键
跟踪 getLifecycle() 代码,发现它的具体实现是在 AppCompatActivity 的祖先类 SupportActivity 中,该类实现了 LifecycleOwner 接口。
在 onSaveInstanceState() 方法中将 mLifecycleRegistry 的状态置为了 Lifecycle.State.CREATED,这点我们在前篇也讲到过。但从这我们还是看不到跟生命周期有关的东西。此时,我们发现在 onCreate() 方法中有这一行代码:
1ReportFragment.injectIfNeededIn(this);
ReportFragment 是做什么的?点进去看:
可以看到, ReportFragment 的 injectIfNeededIn(Activity activity)
方法向 Activity 中添加了一个未设置布局的 Fragment :
然后又在重写的生命周期事件中调用dispatch(Lifecycle.Event event)
方法,来分发生命周期事件,这就是“生命周期感知能力”的来源。这种通过一个空的 Activity 或者 Fragment 来实现特定功能的技巧还是挺常见的,比如权限请求库 RxPermission ,以及 airbnb 开源的用于URL跳转的 DeepLinkDispatch(前者是使用空的 Fragment,后者使用的是空的 Activity)
ReportFragment#dispatch(Lifecycle.Event event)
这里面,又调用了 LifecycleRegistry 的handleLifecycleEvent(event)
方法。至此,就引入了第二个问题,事件是如何分发到 LifecycleObserver 的。
事件是如何分发到 LifecycleObserver 的
进入 LifecycleRegistry#handleLifecycleEvent(Lifecycle.Event event)
方法,发现它又调用了 moveToState(State next)
方法:
而在 sync()
方法中,根据 state 的状态,最终会调用到backwardPass(...)
或者forwardPass(...)
:
以 forwardPass(...)
为例:
上图可以看到,通过 mObserverMap 最终获取到一个 ObserverWithState 类型的 observer 对象,并调用它的dispatchEvent
进行事件分发:
1 observer.dispatchEvent(lifecycleOwner, upEvent(observer.mState));
ObserverWithState
又是个什么鬼?我们继续追踪,发现 ObserverWithState 是 LifecycleRegistry 的一个静态内部类。
从名称上就能看出,该类封装了 Observer 对象和 State 对象(具体就是 State
和 GenericLifecycleObserver
,GenericLifecycleObserver 是个接口,继承自 LifecycleObserver),在其 dispatchEvent 方法中,最终会回调 mLifecycleObserver 的 onStateChanged(...)
方法。
追踪到这里,我们知道了,Lifecycle在监听到生命周期变化之后,最终会回调 GenericLifecycleObserver 的 onStateChanged() 方法。我们不由得疑惑,我们定义的 MyObserver 哪去了?没看到有调用我们定义的回调方法啊。它和 GenericLifecycleObserver 又有什么关系?
我们看到,ObserverWithState 的构造函数里传进来了一个 LifecycleObserver 类型的 observer 对象,这个参数是从哪传进来的?继续追踪,发现追到了LifecycleRegistry#addObserver(LifecycleObserver observer)
方法。
而这个方法,就是我们在MainActivity#onCreate(...)
方法中调用的:
1 getLifecycle().addObserver(new MyObserver());
到这里,总算跟我们的 MyObserver 关联上了。查看LifecycleRegistry#addObserver(LifecycleObserver observer)
方法源码:
这里面的核心代码就两行,一行是:
1 ObserverWithState statefulObserver = new ObserverWithState(observer, initialState);
这行代码,通过传进来的Observer
对象,创建出 ObserverWithState 对象。还有一行是:
1 ObserverWithState previous = mObserverMap.putIfAbsent(observer, statefulObserver);
这行代码是将 LifecycleObserver 对象放入一个FastSafeIterableMap 中,以便进行迭代。
接下来我们就进入 ObserverWithState 的构造方法中看看:
在构造方法中,通过 Lifecycling.getCallback(observer)
根据传进来的 observer ,构造了一个 GenericLifecycleObserver 类型的 mLifecycleObserver ,那秘密应该也就在这个方法里,继续跟进。
这个方法的本质,其实就是根据传进来的一个LifecycleObserver 对象,构造出来一个 GenericLifecycleObserver 对象(目前有四个子类:FullLifecycleObserverAdapter
、SingleGeneratedAdapterObserver
、CompositeGeneratedAdaptersObserver
、ReflectiveGenericLifecycleObserver
),而最终构造出来的对象,就包含了我们创建的 LifecycleObserver 的所有信息,包括各种回调方法等。
看到这里,就要提到文章开头要大家添加的一个注解处理器的依赖:
1annotationProcessor "android.arch.lifecycle:compiler:1.1.1"
当我们通过注解的方式来自定义LifecycleObserver 的时候,按照传统方式,必定要通过反射来对注解进行解析,这样就会对性能造成影响。一方面,我们通过缓存,来避免每次都通过反射获取构造器。另一方面,又通过注解处理器,在编译时对那些被@OnLifecycleEvent
注解标注的普通方法,进行预处理,生成以“类名_LifecycleAdapter”命名的类,将各种回调方法直接进行逻辑转换,避免反射,进而来提高性能。
明白了这点,再看Lifecycling.getCallback(observer)
方法就比较容易理解了。
- 如果传进来的的参数 object 是 FullLifecycleObserver 类型,就把它构造成FullLifecycleObserverAdapter 对象,并返回
- 如果传进来的的参数 object 是GenericLifecycleObserver类型,直接返回该对象
- 如果1,2都不满足,就解析该类的的构造器的Type(该类是反射获取的,还是通过注解处理器生成的)。如果是通过注解处理器生成的类来调用回调函数,就返回一个SingleGeneratedAdapterObserver/CompositeGeneratedAdaptersObserver 对象
- 如果以上条件都不满足,就通过反射来调用各回调函数。返回一个 ReflectiveGenericLifecycleObserver 对象
现在我们在 app 目录下的 bulid.gradle
中添加上上面的注解处理器依赖,然后编译下项目,会发现在build目录下生成了对应的类:MyObserver_LifecycleAdapter.java
点进去,看看生成的这个类的源码:
可以看到,我们在 MyObserver 中通过@OnLifecycleEvent
注解标注的那些方法,在这里都根据条件进行判断了,而非通过注解。
这时候我们就能理清这个这个流程了,当添加了注解处理器之后,我们这里的Lifecycling.getCallback(observer)
方法将会把我们的MyObserver
对象构建成一个 SingleGeneratedAdapterObserver
对象返回(因为这里只有一个构造器),之后的 mLifecycleObserver.onStateChanged(owner, event);
其实调用的就是SingleGeneratedAdapterObserver
的onStateChanged(owner, event)
方法:
这里面就可以看到,它调用了内部包裹的类的callMethods(...)
方法,也就是我们上面提到的MyObserver_LifecycleAdapter
的callMethonds(...)
方法。
到这里,就完成了 Lifecycle 源码的解析。
通过反射获取注解信息
这顺便提下通过注解的方式调用各回调方法的过程。主要相关类就是 ReflectiveGenericLifecycleObserver.java
这里我们主要关注回调信息 CallbackInfo
的获取方式的代码: mInfo = ClassesInfoCache.sInstance.getInfo(mWrapped.getClass());
因为反射的代价是比较大的,所以又通过 ClassesInfoCache.java
这个单例类,为 ReflectiveGenericLifecycleObserver 类要调用的各种方法的相关信息进行了缓存。
点进去看下它的 getInfo(...)
方法内部,是如何获取方法信息的。
里面又调用了createInfo()
方法:
这里,就能看到对注解进行处理的代码了。
到这,我们就算完成了继承自 AppCompactActivity 的情况下的源码解析,而继承自普通 Activity 这种情况下,原理是什么呢?
鉴于篇幅,将放在下篇文章。欢迎关注我的公众号获取。
android 生命周期_Android生命周期组件 Lifecycle 源码详解(一)相关推荐
- Lifecycle 源码详解
Lifecycle 是 Jetpack 整个家族体系内最为基础的内容之一,正是因为有了 Lifecycle 的存在,使得如今开发者搭建依赖于生命周期变化的业务逻辑变得简单高效了许多,使得我们可以用一种 ...
- Android 事件分发机制分析及源码详解
Android 事件分发机制分析及源码详解 文章目录 Android 事件分发机制分析及源码详解 事件的定义 事件分发序列模型 分发序列 分发模型 事件分发对象及相关方法 源码分析 事件分发总结 一般 ...
- 源码详解Android 9.0(P) 系统启动流程之SystemServer
源码详解Android 9.0(P) 系统启动流程目录: 源码详解Android 9.0(P)系统启动流程之init进程(第一阶段) 源码详解Android 9.0(P)系统启动流程之init进程(第 ...
- Android AR开发实践之七:OpenGLES相机预览背景绘制源码详解
Android AR开发实践之七:OpenGLES相机预览背景绘制源码详解 目录 Android AR开发实践之七:OpenGLES相机预览背景绘制源码详解 一.OpenGL ES渲染管线 1.基本处 ...
- ios navigation的返回按钮长按_Android Jetpack架构组件 — Navigation入坑详解 [转]
前言 这是最近看见的觉得比较有意思的文,希望对大家的学习有帮助. Navigation 直接翻译即为导航,它是 Android Jetpack 组件之一,让单 Activity 应用成为首选架构.应用 ...
- android pcm 音量_Android中实时获取音量分贝值详解
基础知识 度量声音强度,大家最熟悉的单位就是分贝(decibel,缩写为dB).这是一个无纲量的相对单位,计算公式如下: 分子是测量值的声压,分母是参考值的声压(20微帕,人类所能听到的最小声压).因 ...
- Android编程之DialogFragment源码详解(二)
接上篇,继续: 然后就是setShowsDialog(boolean showsDialog)方法.官方文档是这样解释的:控制DialogFragment是否是一个dislog,如果设置为false, ...
- Android编程之LocalBroadcastManager源码详解
LocalBroadcastManager 是V4包中的一个类,主要负责程序内部广播的注册与发送.也就是说,它只是适用代码中注册发送广播,对于在AndroidManifest中注册的广播接收,则不适用 ...
- Android进阶笔记:Messenger源码详解
Messenger可以理解为一个是用于发送消息的一个类用法也很多,这里主要分析一下再跨进程的情况下Messenger的实现流程与源码分析.相信结合前面两篇关于aidl解析文章能够更好的对aidl有一个 ...
最新文章
- 快排递归非递归python_Python递归神经网络终极指南
- Delphi Code Editor 之 编辑器选项
- ubuntu开机启动管理
- 【学术相关】新一轮“双一流”名单公布!这些学校上榜
- 利用Runtime修改UIdatePicker的字体颜色
- PHP的simplexml_load_string
- WINDOWS 2008 AD权限管理服务(ADRMS)完全攻略
- 论DATASNAP远程方法支持自定义对象作参数
- excel高级筛选怎么用_python中实现excel的高级筛选
- C++文件操作与文件流
- Lugre摩擦模型的Stribeck曲线仿真
- 程序员顶尖和普通就是有5个区别!
- IDEA 不提示报错 和有波浪线
- content='width=device-width, initial-scale=1.0'的解释
- 【机器学习】 - 决策树(西瓜数据集)
- 软件设计师刷题(2)
- 如何有效的快速处理恶意差评?
- 1万字精讲,这你还学不废?Python爬取腾讯视频《斛珠夫人》弹幕,并转换成词云(单线程)——爬虫实例2
- DataFrame,pandas索引,重置索引
- C#之FIFO算法实现页面置换算法
热门文章
- pdo mysql like_PHP PDO准备的语句-MySQL LIKE查询
- mysql 命令 _mysql 命令
- hashset java 键值对_Java中的各个容器的性能对比
- [蓝桥杯][算法提高VIP]排队打水问题(贪心)
- 随机森林做特征重要性排序和特征选择
- python使用redis教程 敲黑板划重点
- MAC电脑安装Python3下的Jupyter Notebook
- linux sd卡 u盘区别,linux下实现U盘和sd卡的自动挂载
- python调用msf_MSF利用python反弹shell-Bypass AV
- 『设计模式』电话接线员与中介者模式