Activity、View、Window的理解一篇文章就够了

  作者:细卷子

  博客:http://www.jianshu.com/u/511ccb5a2012

  要了解这三者之间的关系,我们带着问题通过分析源码一步一步来揭开它们的神秘面纱!

  文章有点长,首先要理解Activity、View、Window,我提出了一些问题,这篇文章可以解答如下问题:

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

  2、Activity工作过程是什么样的?(理解Activity)

  3、Window是什么?它的职能是什么?

  4、View跟Window有什么联系?

  5、Activity、View、Window三者如何关联?

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

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

  Activity就像工匠,Window就像是窗户,View就像是窗花,LayoutInflater像剪刀,Xml配置像窗花图纸。

  Android根据他们不同的职能让他们各斯其活,同时也相互配合展示给我们灵活、精致的界面。

  一张图理清所有层级关系:

  好了,接下来一步一步的分析,首先从大家最熟悉的Activity开始:

  我们的工匠大神Activity

  一个应用程序里所有的界面展示都来自于Activity,那Activity是如何工作的呢?

  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方法

  Activity其他生命周期的调用都是通过Binder向AMS发请求,然后执行的PIC操作,最后从ApplicationThread对生命周期调用。

  下面是重点:Activity、View、Window三者的关系。

  美丽的窗花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上,而View通过WindowManager的addView()、removeView()、updateViewLayout()对View进行管理。Window的添加过程以及Activity的启动流程都是一次IPC的过程。Activity的启动需要通过AMS完成;Window的添加过程需要通过WindowSession完成。

  你竟然看完了,非常感谢你的支持,希望这篇文章对你有帮助~

  大连妇科医院 http://www.403yy.com/

  大连人流医院 http://www.dlrlyy.net/

原文地址:https://www.cnblogs.com/lll123/p/10716476.html

时间: 2024-11-05 17:18:07

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

(转) TensorFlow深度学习,一篇文章就够了

TensorFlow深度学习,一篇文章就够了 2016/09/22 · IT技术 · TensorFlow, 深度学习 分享到:6 原文出处: 我爱计算机 (@tobe迪豪 ) 作者: 陈迪豪,就职小米科技,深度学习工程师,TensorFlow代码提交者. TensorFlow深度学习框架 Google不仅是大数据和云计算的领导者,在机器学习和深度学习上也有很好的实践和积累,在2015年年底开源了内部使用的深度学习框架TensorFlow. 与Caffe.Theano.Torch.MXNet等框

面试题-关于Java线程池一篇文章就够了

在Java面试中,线程池相关知识,虽不能说是必问提,但出现的频次也是非常高的.同时又鉴于公众号"程序新视界"的读者后台留言让写一篇关于Java线程池的文章,于是就有本篇内容,本篇将基于Java线程池的原理.实现以及相关源码进行讲解等. 什么是线程池 线程池是一种多线程处理形式,处理过程中将任务提交到线程池,任务的执行交由线程池来管理. 为了充分利用CPU多核资源,应用都会采用多线程并行/并发计算,最大限度的利用多核提升应用程序性能. 试想一下,如果每个请求都执行一遍创建线程.执行任务.

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

前言 在决定用这个标题之前甚是忐忑,主要是担心自己对AIDL的理解不够深入,到时候大家看了之后说--你这是什么玩意儿,就这么点东西就敢说够了?简直是坐井观天不知所谓--那样就很尴尬了.不过又转念一想,我辈年轻人自当有一种一往无前的锐气,标题大气一点岂不更好?并且大家都是文明人,总归更多的是理解与补充而不是侮辱与谩骂?所以最终还是厚颜用了这么一个不怎么有耻的标题. 好了,接下来进入正题,谈谈我对AIDL的理解和认识. 正文 1,概述 AIDL是一个缩写,全称是Android Interface D

彻底理解Netty,这一篇文章就够了

Netty到底是什么 从HTTP说起 有了Netty,你可以实现自己的HTTP服务器,FTP服务器,UDP服务器,RPC服务器,WebSocket服务器,Redis的Proxy服务器,MySQL的Proxy服务器等等. 我们回顾一下传统的HTTP服务器的原理 1.创建一个ServerSocket,监听并绑定一个端口 2.一系列客户端来请求这个端口 3.服务器使用Accept,获得一个来自客户端的Socket连接对象 4.启动一个新线程处理连接 4.1.读Socket,得到字节流 4.2.解码协议

关于HTTPS一篇文章就够了

欢迎转载,转载请标明出处: http://blog.csdn.net/johnny901114/article/details/54754921 本文出自:[余志强的博客] HTTP是明文请求的,它的域名.路径和参数都被中间人看得一清二楚.Google鼓励所有的网站都要使用Https,AppStore也要求新的app也要是https协议,随着各大巨头对网络安全的重视,对用户隐私的重视,是时候系统的研究下Https了. 以前在开发App的时候,在App里面内嵌H5界面,我们这个H5是http协议的

扩展方法从简单应用到深入解析,读这一篇文章就够了

前言(扯淡-_-) 大家好,今天和大家聊聊扩展的事,我将带着大家从简单应用开始深入理解扩展方法的原理,并对扩展方法的使用给出合理的建议. 在实际应用中,当我们在使用某类时发现类中缺少我们想要的方法,最简单直接的就是修改类的源代码来添加我们想要的方法.但事实往往不如人意,总会因为各种因素不可以直接修改源码:拿不到源码.不允许修改,这时候通过继承并扩展的方式来复用是再好不过了,但是如果连最后的继承的权利都剥夺的话(密封类不允许继承)?...这时候就需要用到[扩展方法]了. 扩展方法简介 我们先来看看

maven一篇文章就够了(上)

一:maven的发展历程 在maven发展之前,传统的jar包管理我们一般会用ant+lvy来管理jar包,它有显而易见的两个缺点, 缺点一:需要我们来手动的来打jar包(build as),然后把打过得包放到我们规定的目录下(虽然可以进行特殊的处理引用本地的应用,不需要打包,但是前提条件就是你的有这个应用的源码). 缺点二:每一个应用都需要有相同的配置,重复的工作不停的在做,这样的话相当月重复造轮子,这也不太符合编程语言的原则. 基于这两点:我们从农业社会开始向工业社会转型,开始步入maven

Dart入门?一篇文章就够了!

近期公司准备启动新项目,经过技术团队一番调研,决定采用 Flutter 来开发第一版App,故作此文,常来回顾温习.由于项目采用敏捷开发模式,故本文主要总结和记录 Dart 常用语法,更多高级和生僻用法将在后面开发过程中不定期更新. First of all 在我们正式接触 Dart 语法之前,需要铭记以下内容,这将会对后续 Dart 语法的学习.理解和应用有很大帮助: 万物皆对象, 每个对象都是一个类的实例.在 Dart 中,甚至连数字.方法和 null 都是对象,并且所有的对象都继承于 Ob

100JAVA设计模式看着一篇文章就够了!

学JAVA设计模式,会遇到一下几个难题: 1.记不住 a.记不住7大原则,23种设计模式! b.不能复述设计模式代码,UML图! 2.看不懂 a.看不懂代码演示! b.看不懂高手代码! c,看不懂框架代码! 3.不会用 业务逻辑处理怎么用? 业务变更怎么用? 业务扩展怎么用? 4.带你看懂Spring源码中各种设计模式,充分理解架构设计中大师如何构建高扩展系统! 原文地址:https://www.cnblogs.com/gcq243627152qq/p/12003808.html