原址

要了解这三者之间的关系,我们带着问题通过分析源码一步一步来揭开它们的神秘面纱! 
文章有点长,首先要理解Activity、View、Window,我提出了一些问题,这篇文章可以解答如下问题: 
1、为什么要设计Activity、View、Window? 
2、Activity工作过程是什么样的?(理解Activity) 
3、Window是什么?它的职能是什么? 
4、View跟Window有什么联系? 
5、Activity、View、Window三者如何关联?

1、为什么要设计Activity、View、Window?

用一句话来联系他们之间的关系:

Activity就像工匠,Window就像是窗户,View就像是窗花,LayoutInflater像剪刀,Xml配置像窗花图纸。 
Android根据他们不同的职能让他们各斯其活,同时也相互配合展示给我们灵活、精致的界面。

一张图理清所有层级关系: 
 
好了,接下来一步一步的分析,首先从大家最熟悉的Activity开始:

我们的工匠大神Activity

Activity工作过程: 
启动: 
从startActivity开始,它会调用到Instrumentation,然后Instrumentation通过Binder向AMS(ActivityManagerService)发请求,通过PIC启动Activity。而这个AIDL操作的方法定义在ApplicationThread中(里面包括了Activity所有的生命周期方法的调用)。然后通过Handle回到主线程启动activity。 
因为中间流程太多,详细写出来容易造成“见其树木,而不见其森林”的局面。

启动Activity所执行的操作: 
1、从ActivityClientRecord中获取待启动的Activity组件信息 
2、通过Instrumentation的newActivity方法使用类加载器创建Activity对象 
3、通过LoadedApk的mackApplication方法来尝试创建Application对象(如果Application已经创建,则不会重复创建) 
4、创建ContextImpl对象,并通过Activity的attach方法来完成一些重要数据的初始化(包括让Activity跟Window关联) 
5、调用Activity的onCreate方法

美丽的窗花View

View如何跟Activity关联起来的? 
其实View并不是直接跟Activity关联起来的,而是通过Window这个中间人。如前面所说,View只是窗花,Window才是直接关联到Activity上的。那么: 
View如何跟Window关联起来呢?

下面先了解一下Window,就可以理解这个问题了

灵活的窗户Window

Window如何跟Activity关联? 
每一个Activity都包含了唯一一个PhoneWindow,这个就是Activity根Window(之所以是说根Window是因为在它上面可以增加更多其他的Window,例如:弹出框(dialog))

那么,PhoneWindow如何跟Activity关联起来的呢? 
来个最简单的,setContentView其实就让View与Window关联,Window跟Activity关联起来了。

那setContentView不是View跟Activity关联吗? 
真相见Activity源码: 

明显是将layout设置到Window上了,那这个 getWindow() 返回的Window是谁呢? 是不是前面提及PhoneWindow? 
 

真的是PhoneWindow,在 attach 的时候执行了PhoneWindow的初始化。 
提到了 activity 的 attach 方法,该方法是在执行Activity启动时在ActivityThread里面的performLaunchActivity调用的。performLaunchActivity里面做了很多Activity启动过程具体的操作,例如:主题、记录Activity栈、执行Activity onCreate 方法等。 
这么说来setContentView其实就是将View设置到Window上,Activity展示的其实是PhoneWindow上的内容。那么其实 setContentView 实际上是调用的 getWindow().setContentView。

PhoneWindow是个什么东西?它作为Activity跟View的中间人,它做了哪些工作? 

首先 PhoneWindow 本身就是一个 Window。

从setContentView来分析: 

这里的 mContentParent 其实是一个 ViewGroup。这么看来就简单了。PhoneWindow里面包含了一个ViewGroup,setContentView其实就是将layout设置到了这个ViewGroup上了。

我们再看看这张图: 
 
DecorView是啥? 
它直接跟PhoneWindow关联起来的,有了mContentParent,为啥还需要DecorView? 
如图所见,DecorView它不仅包含了我们自己的布局,它还包含了titleBar。为啥需要?结构上的需要,更好的管理布局。

Window作为中间人,已经关联了Activity跟View了,那么如果处理Activity跟View之间的关系呢? 
是时候揭开Window这个神秘面纱了: 
之前提的PhoneWindow是继承于Window的,它是连接Activity跟View之间的桥梁。所有对View的一些操作都需要借助这个桥梁。

为了更好的理解Window,我们先从Dialog入手。在Activity中展示一个对话框的流程是怎样的? 
为啥从Dialog入手,因为它里面包含了Window,而且可以直接操作Window里面的View,这样就能了解Window是如何控制View的,以及自定义Window怎么展示到Activity上(因为了解Dialog,就知道怎么让自定义的Window与Activity关联了)

我们省去所有的Dialog build的方法。直接从AlertDialog.show()方法开始: 
 
可见show()方法里面执行了create()方法,继续看create()方法做了什么事:
new 了一个 AlertDialog,那么跟踪它的构造方法看看: 

AlertDialog构造方法里面最后执行的是这个构造方法,这里找到了亮点: 
1、mWindow是啥?是不是PhoneWindow? 
首先AlertDialog是继承Dialog的,mWindow就是Dialog里面初始化的对象,看看是不是PhoneWindow,如果是,那么就可以猜到通过在PhoneWindow添加View就可以在Activity上展示了,因为经过上面分析Activity是跟PhoneWindow有关联的。带着问题继续分析源码: 

果然如此,太开心了。

2、AlertController是啥? 

从这两个属性就知道了,设置Title、Message的。用过Dialog的人都知道他们是啥,就不多说了。

既然这样关联起来了,那么Window怎么对View操控的呢? 

WindowManager是主角。 
在Dialog build之后就将View设置进来了,继续追踪Dialog show()这个方法,这个方法会将View与Window相互联系: 


因为电脑屏幕大小受限,就截了两个图。 
mWindowManager.addView,看到这个方法,可以猜想到WindowManager是个啥玩意了。 

从源码注释可看出,WindowManager是对Window进行操作的。它可以做哪些操作? 

好了,真相揭晓了。Window对View的操作是通过WindowManager来处理的。WindowManager提供在Window上添加View、移除View、更新View的操作。 
然而可见 WindowManager 其实只是一个接口,真正的实现类是WindowManagerImpl 
以addView为例,里面有点绕,直接忽略中间过程,最后执行addView的是通过ViewRootImpl完成Window的添加工作的,它执行了View的requestLayout方法,在requestLayout方法里会通过WindowSession完成Window的添加过程WindowSession是IWindowSession类型的,它是一个Binder对象,因此Window的添加工作其实是一次IPC调用。好了,大致流程就是如此,这样就更新界面了。

总结: 
1、为什么要设计Activity、View、Window? 
Activity就像工匠,Window就像是窗户,View就像是窗花,LayoutInflater像剪刀,Xml配置像窗花图纸。 
Android根据他们不同的职能让他们各斯其活,同时也相互配合展示给我们灵活、精致的界面。为啥这样设计?因为这样的结构更好管理。就像为啥需要使用MVP、MVVM、各种设计模式一样。

2、Activity工作过程是什么样的? 
以Activity启动过程为例,Activity启动时是通过Binder向AMS(ActivityManagerService)发请求,通过PIC启动Activity的。

3、Window是什么?它的职能是什么? 
Activity要管理View需要通过Window来间接管理的。Window通过addView()、removeView()、updateViewLayout()这三个方法来管理View的。

4、View跟Window有什么联系? 
View需要通过Window来展示在Activity上。

5、Activity、View、Window三者如何关联? 
Activity包含了一个PhoneWindow,而PhoneWindow就是继承于Window的,Activity通过setContentView将View设置到了PhoneWindow上。Window的添加过程以及Activity的启动流程都是一次IPC的过程。Activity的启动需要通过AMS完成;Window的添加过程需要通过WindowSession完成。

Activity、View、Window的理解一篇文章就够了相关推荐

  1. Android:学习AIDL,这一篇文章就够了(下)

    前言 上一篇博文介绍了关于AIDL是什么,为什么我们需要AIDL,AIDL的语法以及如何使用AIDL等方面的知识,这一篇博文将顺着上一篇的思路往下走,接着介绍关于AIDL的一些更加深入的知识.强烈建议 ...

  2. js层级选择框样式_IOS和JS的交互,看这一篇文章就够了

    IOS和JS的交互,看这一篇文章就够了 创作不易,请珍惜,之后会持续更新,不断完善 Demo地址 目录 WKWebView使用.JS的交互 WKWebView使用.JS的交互 演示(本来想贴张GIF作 ...

  3. 集成Android免费语音合成功能(在线、离线、离在线融合),有这一篇文章就够了(离线)

    原址 集成Android免费语音合成功能(在线.离线.离在线融合),有这一篇文章就够了(在线) 集成Android免费语音合成功能(在线.离线.离在线融合),有这一篇文章就够了(离在线融合)     ...

  4. 全面认识MOS管,一篇文章就够了

    基础知识中 MOS 部分迟迟未整理,实际分享的电路中大部分常用电路都用到了MOS管, 今天势必要来一篇文章,彻底掌握mos管! ...更新:为什么常在MOS管GS并联电阻? ...更新:为什么要在MO ...

  5. 全面认识二极管,一篇文章就够了

    电子设计基础元器件 二极管,小小二极管,大大用途. ... 矜辰所致 目录 前言 一.二极管基础知识 1.1 什么是二极管 1.2 二极管的组成 1.3 二极管的原理 二.二极管特性 2.1 伏安特性 ...

  6. MySQL优化-一篇文章就够了(转发加收藏吧)

    关注我,一个仍存梦想的屌丝程序员,每天为你分享高质量编程博客. 回复 "代金券"  免费获取腾讯云和阿里云代金券 前言 说起MySQL的查询优化,相信大家收藏了一堆:不能使用SEL ...

  7. 学习 HTML5 Canvas 这一篇文章就够了

    一.canvas 简介 ​<canvas> 是 HTML5 新增的,一个可以使用脚本(通常为 JavaScript) 在其中绘制图像的 HTML 元素.它可以用来制作照片集或者制作简单(也 ...

  8. 如何使用 Maven 来创建项目(一篇文章就够了)

    如何使用 Maven 来创建项目(一篇文章就够了) 1. Maven 简介 1. 简介 2. 项目构建 3. 项目构建工具 2. Maven 的四大特性 1. 依赖管理系统 版本号规范 2. 多模块构 ...

  9. 架构师必须搞懂DNS,一篇文章就够了。

    转载自 架构师必须搞懂DNS,一篇文章就够了. 概念 DNS,全称Domain Name System,即域名系统,搞清楚,它不是DNF地下城与勇士. DNS是怎么来的,我们知道要访问一个服务器的资源 ...

最新文章

  1. 记一次TIME_WAIT网络故障
  2. Java黑皮书课后题第7章:7.16(执行时间)编写程序,随机产生一个包含100 000个整数的数组和一个关键字。估算调用程序清单7-6中的linearSearch方法的执行时间
  3. 对两个字符串进行比较,取出两个字符串中一样部分的长度
  4. Office 365 Outlook Web App 移动设备体验
  5. 阿里云HPC--人工智能加速利器
  6. Excel数据分析学习笔记(三)Excel常用数据分析工具(需要统计学基础)
  7. 【2021LaTeX模板分享】数学建模竞赛国赛
  8. CityEngine--comp() operator
  9. 日历插件(项目总结)(包括mobiscroll.js LCalendar 和Calendar这三个日历插件)
  10. linux修改vnc设置密码,更改root与vnc密码,配置vnc
  11. 【浏览器被劫持解决方案】https://www.hao123.com/?tn=9762xxxx2644_hao_pg
  12. 天地不仁,通货在膨胀
  13. html边框设置为背景同色,css边框与背景
  14. 用简单的lnmp实现的论坛搭建
  15. 【本人秃顶程序员】作为字节跳动的研发面试官,有些话我不得不说!
  16. 7.3 写一个判断素数的函数,在主函数输入一个整数,输出是否为素数的信息。
  17. 【来日复制粘贴】关于排名
  18. 员工被提拔,还是被干掉,就看这3点......
  19. Python实现超简单【抖音】无水印视频批量下载
  20. 三菱Q程序程序 用三菱Q系列和威纶触摸屏编写

热门文章

  1. 调用内部类里,在静态类中调用动态方法的问题
  2. (转)一种高速内存校验算法(Delphi MMX优化算法应用之一)
  3. OpenDocument Format ODF
  4. 滑铁卢大学计算机科学双录取,滑铁卢大学双录取要求
  5. FastReport问题整理
  6. 堆和栈的概念和区别?
  7. repo同步代码_一次协作多端同步,打通看云、github互相同步(serverless实践)
  8. java 内部类 加载_Java 内部类基础介绍
  9. mybatis的mysql分页_使用MyBatis+Mysql实现分页的插件PageInfo使用介绍
  10. linux rm 文件找回_Linux 中删除目录的多种方法