Activity系列博客5篇
目录介绍
- 01.前沿介绍
- 02.handleLaunchActivity
- 03.performLaunchActivity
- 04.activity.attach
- 05.Activity的onCreate方法
- 06.setContentView
- 07.关于一点总结
Activity一系列深度博客,挖掘activity从启动过程,到布局创建,以及绘制的过程。
吕诗禹想换个工作,渴望同行内推
- 个人信息
- 姓名:吕诗禹
- 邮箱:17801164348@163.com
- 微信:13940574490
- GitHub:https://github.com/yangchong211
- 目前工作情况:在职状态
- 工作年限:4年
- 工作地点:北京
- 感谢同行朋友,如果可以,可以直接电话联系或者微信联系!
01.前沿介绍
- 大家都知道在Android体系中Activity扮演了一个界面展示的角色,这也是它与android中另外一个很重要的组件Service最大的不同,但是这个展示的界面的功能是Activity直接控制的么?界面的布局文件是如何加载到内存并被Activity管理的?android中的View是一个怎样的概念?加载到内存中的布局文件是如何绘制出来的?
- 其实Activity对界面布局的管理是都是通过Window对象来实现的,Window对象,顾名思义就是一个窗口对象,而Activity从用户角度就是一个个的窗口实例,因此不难想象每个Activity中都对应着一个Window对象,而这个Window对象就是负责加载显示界面的。至于window对象是如何展示不同的界面的,那是通过定义不同的View组件实现不同的界面展示。
02.handleLaunchActivity
- 当ActivityManagerService接收到启动Activity的请求之后会通过IApplicationThread进程间通讯告知ApplicationThread并执行handleLauncherActivity方法,这里可以看一下其具体实现:
- 可以发现这里的handleLauncherActivity方法内部调用了performLaunchActivity方法。
03.performLaunchActivity
- 这个方法也是具体启动Activity的方法,我们来看一下它的具体实现逻辑:
- 从代码中可以看到这里是通过反射的机制创建的Activity,并调用了Activity的attach方法,那么这里的attach方法是做什么的呢?
04.activity.attach
- 我们继续来看一下attach方法的实现逻辑:
- 可以看到在attach方法这里初始化了一些Activity的成员变量,主要是mWindow对象,并且mWindow的成员实例是PhoneWindow实例,这样也从侧面说明了一个Activity对应着一个Window对象。除了window对象还初始化了一些Activity的其他成员变量,这里不再做讨论,继续回到我们的performLaunchActivity方法,在调用了Activity的attach方法之后又调用了:
- 这里的mInstrumentation是类Instrumentation,每个应用进程对应着一个Instrumentation和一个ActivityThread,Instrumentation就是具体操作Activity回调其生命周期方法的,我们这里看一下它的callActivityOnCreate方法的实现:
- 这里代码比较简洁,preOerformCreate方法和postPerformCreate方法我们这里暂时不管,主要的执行逻辑是调用了activity.performCreate方法,我们来看一下Activity的performCreate方法的实现:
- 原来onCreate的生命周期方法是在这里回调的,其实这里的逻辑在前面几篇文章中有讲述,也可以参考前面的文章。
05.Activity的onCreate方法
- 至此就回调到了我们Activity的onCreate方法,大家平时在重写onCreate方法的时候,怎么加载布局文件的呢?这里看一下我们的onCreate方法的典型写法:
- 无论我们怎么变化,我们的onCreate方法一般都是会调用这两句话的吧?那么这里的两段代码分辨是什么含义呢?我们首先看一下super.onCreate方法的实现逻辑,由于我们的Activity类继承与Activity,所以这里的super.onCreate方法,就是调用的Activity.onCreate方法,好吧,既然这样我们来看一下Activity的onCreate方法:
- 可以发现,Activity的onCreate方法主要是做了一些Acitivty的初始化操作,那么如果我们不在自己的Activity调用super.onCreate方法呢?好吧,尝试之后,AndroidStudio在打开的Acitivty的onCreate方法中如果不调用super.onCreate方法的话,会报错。。。
- 可以看到如果不调用super.onCreate方法的话,会在Activity的performLaunchActivity中报错,我们知道这里的performLaunchActivity方法就是我们启动Activity的时候回回调的方法,我们找找方法体实现中throws的Exception。。。
- 在Activity的performLaunchActivity方法中,我们在调用了Activity的onCreate方法之后会执行一个判断逻辑,若Activity的mCalled为false,则会抛出我们刚刚捕获的异常,那么这个mCalled成员变量是在什么时候被赋值的呢?好吧,就是在Activity的onCreate方法赋值的,所以我们在实现自己的Activity的时候只有调用了super.onCreate方法才不会抛出这个异常,反过来说,我们实现自己的Actiivty,那么一定要在onCreate方法中调用super.onCreate方法。
06.setContentView
- 然后我们在看一下onCreate中的setContentView方法,这里的参数就是一个Layout布局文件,可以发现这里的setContentView方法就是Acitivty中的setContentView,好吧我们来看一下Activity中setContentView的实现:
- 这里的getWindow方法就是获取Acitivty的mWindow成员变量,从刚刚我们在Activity.attach方法我们知道这里的mWindow的实例是PhoneWindow,所以这里调用的其实是PhoneWindow的setConentView方法,然后我们看一下PhoneWindow的setContentView是如何实现的。
- 这里的mContentParent对象是一个View对象,由于第一次mContentParent为空,所以执行installerDector方法,这里我们看一下installerDector方法的具体实现:
- 这里的mDector是一个DectorView对象,而DectorView继承与FrameLayout,所以这里的mDector其实就是一个FrameLayout对象,并通过调用generateDector()方法初始化,我们继续看一下generateDector方法的具体实现:
- 就是通过new的方式创建了一个DectorView对象,然后我们继续看installDector方法:
- 这里初始化了mContentParent对象,这是一个View对象,我们调用了generateLayout方法,好吧,来看一下generateLayout方法的具体实现:
- 可以发现这里就是通过调用LayoutInflater.inflate方法来加载布局文件到内存中,关于LayoutInflater.inflater是如何加载布局文件的,并且,通过对代码的分析,我们发现PhoneWindow中的几个成员变量:mDector,mContentRoot,mContentParent的关系 mDector --> mContentRoot --> mContentParent(包含)
- 并且我们来看一下典型的布局文件:
- 这里就是整个Activity加载的跟布局文件:screen_simple.xml,其中ViewStub对应着Activity中的titleBar而这里的FrameLayout里面主要用于填充内容。
- 然后我们具体看一下LayoutInflater.inflater方法:
- 这里调用了inflate的重载方法。。。
- 通过分析源码,不难发现,主要是通过循环解析xml文件并将信息解析到内存View对象,布局文件中定义的一个个组件都被顺序的解析到了内存中并被父子View的形式组织起来,这样通过给定的一个root View就可以将整个布局文件中定义的组件全部解析。分析完解析布局文件,回到我们的setContentVIew方法,在调用了installDector方法之后,又调用了:
- 这个方法的含义就是将我们传递的客户端的layoutId对应的布局文件作为mContentParent的子View加载到内存中,这样我们的layoutId作为mContentParent的子View,而mContentParent又是mContentRoot的子View,mContentRoot又是mDector的子View,通过LayoutInflater的inflate方法逐步加载到了内存中,而我们的Activity又持有自身的PhoneWindow的引用,这就相当于我们的Activity持有了我们定义的布局文件的引用,因而Activity的布局文件被加载到了内存中。
07.关于一点总结
- 总结:
- Activity的展示界面的特性是通过Window对象来控制的;
- 每个Activity对象都对应这个一个Window对象,并且Window对象的初始化在启动Activity的时候完成,在执行Activity的onCreate方法之前;
- 每个Window对象内部都存在一个FrameLayout类型的mDector对象,它是Acitivty界面的root view;
- Activity中的window对象的实例是PhoneWindow对象,PhoneWindow对象中的几个成员变量mDector,mContentRoot,mContentParent都是View组件,它们的关系是:mDector --> mContentRoot --> mContentParent --> 自定义layoutView
- LayoutInflater.inflate主要用于将布局文件加载到内存View组件中,也可以设定加载到某一个父组件中;
- 典型的Activity的onCreate方法中需要调用super.onCreate方法和setContentView方法,若不调用super.onCreate方法,执行启动该Activity的逻辑会报错,若不执行setContentView的方法,该Activity只会显示一个空页面。
其他介绍
01.关于博客汇总链接
02.关于我的博客
- github:https://github.com/yangchong211
- 知乎:https://www.zhihu.com/people/yczbj/activities
- 简书:http://www.jianshu.com/u/b7b2c6ed9284
- csdn:http://my.csdn.net/m0_37700275
- 喜马拉雅听书:http://www.ximalaya.com/zhubo/71989305/
- 开源中国:https://my.oschina.net/zbj1618/blog
- 泡在网上的日子:http://www.jcodecraeer.com/member/content_list.php?channelid=1
- 邮箱:yangchong211@163.com
- 阿里云博客:https://yq.aliyun.com/users/article?spm=5176.100- 239.headeruserinfo.3.dT4bcV
- segmentfault头条:https://segmentfault.com/u/xiangjianyu/articles
- 掘金:https://juejin.im/user/5939433efe88c2006afa0c6e
开源地址:https://github.com/yangchong211
Activity系列博客5篇的更多相关文章
- Flutter 即学即用系列博客总结篇
前言 迟到的总结篇,其实大家看我之前发的系列博客最后一篇,发文时间是 3 月 29 日.距离现在快两个月了. 主要是因为有很多事情在忙,所以这篇就耽搁了. 今天终于可以跟大家会面了. 系列博客背景 F ...
- 大数据系列博客之 --- 深入简出 Shell 脚本语言(高级篇)
首先声明,此系列shell系列博客分为四篇发布,分别是: 基础篇:https://www.cnblogs.com/lsy131479/p/9914747.html 提升篇:https://www.cn ...
- 大数据系列博客之 --- 深入简出 Shell 脚本语言(提升篇)
首先声明,此系列shell系列博客分为四篇发布,分别是: 基础篇:https://www.cnblogs.com/lsy131479/p/9914747.html 提升篇:https://www.cn ...
- 大数据系列博客之 --- 深入简出 Shell 脚本语言(基础篇)
首先声明,此系列shell系列博客分为四篇发布,分别是: 基础篇:https://www.cnblogs.com/lsy131479/p/9914747.html 提升篇:https://www.cn ...
- Flutter 即学即用系列博客——05 StatelessWidget vs StatefulWidget
前言 上一篇我们对 Flutter UI 有了一个基本的了解. 这一篇我们通过自定义 Widget 来了解下如何写一个 Widget? 然而 Widget 有两个,StatelessWidget 和 ...
- Flutter 即学即用系列博客——04 Flutter UI 初窥
前面三篇可以算是一个小小的里程碑. 主要是介绍了 Flutter 环境的搭建.如何创建 Flutter 项目以及如何在旧有 Android 项目引入 Flutter. 这一篇我们来学习下 Flutte ...
- Flutter 即学即用系列博客——09 MethodChannel 实现原生与 Flutter 通信(二)
前言 上一篇我们讲解了如何通过 EventChannel 实现 Android -> Flutter 的通信. 并且也看到了 Flutter 内部 EventChannel 源码也是对 Meth ...
- Flutter 即学即用系列博客——09 EventChannel 实现原生与 Flutter 通信(一)
前言 紧接着上一篇,这一篇我们讲一下原生怎么给 Flutter 发信号,即原生-> Flutter 还是通过 Flutter 官网的 Example 来讲解. 案例 接着上一次,这一次我们让原生 ...
- Flutter 即学即用系列博客——08 MethodChannel 实现 Flutter 与原生通信
背景 前面我们讲了很多 Flutter 相关的知识点,但是我们并没有介绍怎样实现 Flutter 与原生的通信. 比如我在 Flutter UI 上面点击了一个按钮,我希望原生做一些处理,那么原生怎么 ...
- Flutter 即学即用系列博客——06 超实用 Widget 集锦
本篇文章我们来讲讲一些比较常用的 Widget. 大家验证的时候使用下面的代码替换 main.dart 代码,然后在 //TODO 语句返回下面常用 Widget 示例的代码. import 'pac ...
随机推荐
- Kubernetes 1.26.0实战:在本地配置k8s集群
阶段一:开发环境及版本 以下环境均来自官网: 本地宿主机环境:Windows 10 21H2 64位 虚拟机软件:VMware workstation 15.5 pro 虚拟机镜像版本:ubuntu- ...
- ABC 326
E 题意: 给定一个 \(n\) 面骰,长度 \(n\) 的数组 \(a\) 和一个初始为 \(0\) 的变量 \(x\). 每次投掷骰子,等概率获得 \(1 \sim n\) 中的一个数 \(p\) ...
- NC19158 失衡天平
题目链接 题目 题目描述 终于Alice走出了大魔王的陷阱,可是现在傻傻的她忘了带武器了,这可如何是好???这个时候,一个神秘老人走到她面前答应无偿给她武器,但老人有个条件,需要将所选武器分别放在天平 ...
- Python中Try/Except/else/final语句
python中的try/except/else/finally语句 与其他语言相同,在python中,try/except语句主要是用于处理程序正常执行过程中出现的一些异常情况,如语法错误(pyt ...
- Linux查看系统版本的方法
记录几种查看当前Linux系统的版本的方法 一.使用命令:cat /proc/version 查看 linux版本号:Linux version 5.4.0-99-generic (buildd@lg ...
- flask+xlswriter+axios导出Excel
flask后端 starttime = request.json.get('starttime') endtime = request.json.get('endtime') # 根据时间查询数据库数 ...
- Apipost参数描述的填写和参数描述库的使用
请求参数的描述填写 对于header.query以及form-data和urlencode的body参数,我们在如下地方填写参数描述: 如图中所示,对于一个填写过的参数,我们可以在新建接口可以通过点击 ...
- 2021 虎符杯hate num 注入题
前言 今天遇到个有意思的SQL盲注,花了不少功夫,也学到了新姿势,遂记录下来以备后续碰到相同场景使用. 题目 这是2021 虎符杯的一道web题,有一个目标站点且附带了源码. 源码内容包括: 主要逻辑 ...
- 彩虹猫IDA分析记录
目录 彩虹猫分析 概述 无参启动 带/main参数启动 带/watchdog参数启动 MBR引导程序和动画程序 第一段 引导代码 第二段 动画代码 其他函数 扭曲桌面 扰乱鼠标 钩子函数 桌面绘制图标 ...
- xml中xsd、xsi、xmlns的含义
XML是可扩展标记语言,它定义了按格式编码文件的一系列规则[3],编码的文件是机器可读和人可读的.XML文件对于机器可读是基于XSD(XML Schema Definition)[1]的.XSD是受W ...