专栏首页Android先生Activity、View、Window的理解一篇文章就够了

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

作者:细卷子

地址:http://www.jianshu.com/p/5297e307a688

声明:本文是细卷子原创,已获其授权发布,未经原作者允许请勿转载

要了解这三者之间的关系,我们带着问题通过分析源码一步一步来揭开它们的神秘面纱! 文章有点长,首先要理解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完成。

本文分享自微信公众号 - Android先生(cyg_24kshign),作者:细卷子

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2017-11-14

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 从源码的角度浅谈Activity、Window、View之间的关系

    讲个很简单的例子,这一天天气甚好,小明外出写生,小明背了一包东西,画板啊,纸啊,笔啊什么的,然后小明找了一处风景甚好的地方,从包里拿出画板,纸,笔然后开始画画,...

    用户2802329
  • [译]Android内存泄漏的八种可能(上)

    Java是垃圾回收语言的一种,其优点是开发者无需特意管理内存分配,降低了应用由于局部故障(segmentation fault)导致崩溃,同时防止未释放的内存把...

    用户2802329
  • (新瓶旧酒)谷歌官方MVP项目学习--浅入源码

    项目的目的是通过展示各种架构app的不同方式来帮助开发者解决架构问题。项目中通过不同的架构概念及方式实现了功能相同的app。你可以用示例来当做参考,或是干脆拿来...

    用户2802329
  • Android高频面试专题 - 提升篇(一)Window、View、Activity

    表示一个窗口的概念,是所有View的直接管理者,任何视图都通过Window呈现(点击事件由Window->DecorView->View; Activity的s...

    Android扫地僧
  • Android 性能优化——之控件的优化

      前面讲了图像的优化,接下来分享一下控件的性能优化,这里主要是面向自定义View的优化。

    用户3030674
  • Go并发编程之美-条件变量

    go语言类似Java JUC包也提供了一些列用于多线程之间进行同步的措施,比如低级的同步措施有 锁、CAS、原子变量操作类。相比Java来说go提供了独特的基于...

    加多
  • Go并发编程之美-条件变量

    go语言类似Java JUC包也提供了一些列用于多线程之间进行同步的措施,比如低级的同步措施有 锁、CAS、原子变量操作类。相比Java来说go提供了独特的基于...

    加多
  • 浅谈main(),int main(),void main(),int main(void)四者之间的区别

    Zoctopus
  • 春节假期没玩够?有了它,今年最长能连放 16 天!

    对学生党和上班族来说,最痛苦的一天是哪一天?每个人对于事物的感受不同,答案自然也不同。

    知晓君
  • 带你一起探究Android事件分发机制, 让面试提问不在畏惧!

    大家知道Android中的视图是由一个个View嵌套构成的层级视图,即一个View里包含有子View,而这个子View里面又可以再添加View。当用户触摸屏幕产...

    Android技术干货分享

扫码关注云+社区

领取腾讯云代金券