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 ...
随机推荐
- 《ASP.NET Core 与 RESTful API 开发实战》-- (第10章)-- 读书笔记
第 10 章 部署 10.1 部署到 IIS ASP.NET Core 应用程序支持部署到 IIS 中,之后它将作为应用程序的反向代理服务器和负载均衡器,向应用程序中转传入的 HTTP 请求 默认情况 ...
- Net5 WorkService 继承 Quarzt 以及 Net5处理文件上传
Net5 版本以Core为底层非framework框架的windowservice 服务. 在VS里叫WorkService 可以以CMD方式运行也可以以Windowservice方式运行,部署简单. ...
- 在OAuth 2.0模式下使用Spring Cloud Gateway
Spring Cloud Gateway主要用于以下角色之一: OAuth Client OAuth Resource Server 1 Spring Cloud Gateway as an OAu ...
- Swoole从入门到入土(6)——TCP服务器[粘包]
在了解Swoole下如何处理粘包问题之前,我们需要先了解什么是"粘包".我们以下面这张图进行普及: 假设客户端分别发送了两个数据包D1和D2给服务端,由于服务端一次读取到的字节数是 ...
- postgresql备份和恢复操作
1.介绍 最近项目上用了postgresql数据库,部署的时候需要备份数据库并在现场进行恢复操作,特此记录.我是在windows上安装的pgadmin4,此处用cmd下操作的: 备份命令:pg_dum ...
- ORA-16019 和 ORA-16018 错误的处理方法
一. ORA-16019 和 ORA-16018 错误产生描述 同事在修改归档目录,一不小心把参数设置错误了, 他设置的是log_archive_dest参数. 这个参数和默认log_archive_ ...
- [攻防世界][Web]ics-06
打开靶机对应的url,展开是一个网站的样子,其实啥也么有 所有tab都点一遍,发现只有报表中心有内容,url为 http://61.147.171.105:49797/index.php?id=1 猜 ...
- 函数探秘:深入理解C语言函数,实现高效模块化编程
欢迎大家来到贝蒂大讲堂 养成好习惯,先赞后看哦~ 所属专栏:C语言学习 贝蒂的主页:Betty's blog 1. 函数的概念 在数学中我们就知道了函数这个概念,而C语言同样引入了函数这个概念,那C语 ...
- KPTP 汇报模板
1.什么是KPTP 它是由4个单词:Keep.Problem.Try.Plan的首字母组成的. K:keep,今天做了哪些工作: P:problem,遇到了哪些问题: T:try,计划尝试如何解决这些 ...
- Java JVM——3.运行时数据区概述及线程
运行时数据区概述 在JVM 中的位置 内部划分 当我们通过前面的:类的加载 → 验证 → 准备 → 解析 → 初始化 这几个阶段完成后,执行引擎就会对我们的类进行使用,同时执行引擎将会使用到我们的运行 ...