编程进阶网编程进阶网
  • 基础组成体系
  • 程序编程原理
  • 异常和IO系统
  • 六大设计原则
  • 设计模式导读
  • 创建型设计模式
  • 结构型设计模式
  • 行为型设计模式
  • 设计模式案例
  • 面向对象思想
  • 基础入门
  • 高级进阶
  • JVM虚拟机
  • 数据集合
  • Java面试题
  • C语言入门
  • C综合案例
  • C标准库
  • C语言专栏
  • C++入门
  • C++综合案例
  • C++专栏
  • HTML
  • CSS
  • JavaScript
  • 前端专栏
  • Swift
  • iOS入门
  • 基础入门
  • 开源库解读
  • 性能优化
  • Framework
  • 方案设计
  • 媒体音视频
  • 硬件开发
  • Groovy
  • 常用工具
  • 大厂面试题
  • 综合案例
  • 网络底层
  • Https
  • 网络请求
  • 故障排查
  • 专栏
  • 数组
  • 链表
  • 栈
  • 队列
  • 树
  • 递归
  • 哈希
  • 排序
  • 查找
  • 字符串
  • 其他
  • Bash脚本
  • Linux入门
  • 嵌入式开发
  • 代码规范
  • Markdown
  • 开发理论
  • 开发工具
  • Git管理
  • 百宝箱
  • 开源协议
  • 技术招聘
  • 测试经验
  • 职场提升
  • 技术模版
  • 关于我
  • 目标清单
  • 学习框架
  • 育儿经验
  • 我的专栏
  • 底层能力
  • 读书心得
  • 随笔笔记
  • 职场思考
  • 中华历史
  • 经济学故事
  • 基础组成体系
  • 程序编程原理
  • 异常和IO系统
  • 六大设计原则
  • 设计模式导读
  • 创建型设计模式
  • 结构型设计模式
  • 行为型设计模式
  • 设计模式案例
  • 面向对象思想
  • 基础入门
  • 高级进阶
  • JVM虚拟机
  • 数据集合
  • Java面试题
  • C语言入门
  • C综合案例
  • C标准库
  • C语言专栏
  • C++入门
  • C++综合案例
  • C++专栏
  • HTML
  • CSS
  • JavaScript
  • 前端专栏
  • Swift
  • iOS入门
  • 基础入门
  • 开源库解读
  • 性能优化
  • Framework
  • 方案设计
  • 媒体音视频
  • 硬件开发
  • Groovy
  • 常用工具
  • 大厂面试题
  • 综合案例
  • 网络底层
  • Https
  • 网络请求
  • 故障排查
  • 专栏
  • 数组
  • 链表
  • 栈
  • 队列
  • 树
  • 递归
  • 哈希
  • 排序
  • 查找
  • 字符串
  • 其他
  • Bash脚本
  • Linux入门
  • 嵌入式开发
  • 代码规范
  • Markdown
  • 开发理论
  • 开发工具
  • Git管理
  • 百宝箱
  • 开源协议
  • 技术招聘
  • 测试经验
  • 职场提升
  • 技术模版
  • 关于我
  • 目标清单
  • 学习框架
  • 育儿经验
  • 我的专栏
  • 底层能力
  • 读书心得
  • 随笔笔记
  • 职场思考
  • 中华历史
  • 经济学故事
  • 02.Android虚拟机知识
  • 03.App核心概念分析
  • 04.Android消息机制
  • 05.Android程序UI框架
  • 06.Android应用窗口
  • 07.WMS机制深入分析
  • 08.PMS机制深入分析
  • 09.AMS机制深入分析
  • 11.四大组件原理分析
  • 12.四大组件原理分析
  • 13.View绘制流程分析
  • 14.View渲染流程分析
  • 16.Android绘制原理
  • 17.Android事件传输
  • 18.Android事件拦截
  • 21.View自定义控件反思
  • 22.ViewGroup自定义控件
  • 25.IPC跨进程通信实践
  • 29.Binder机制的理解

06.Android应用窗口

目录介绍

  • 01.Android组件UI实现
    • 1.1 组件的UI实现介绍
    • 1.2 Activity组件类关系
    • 1.3 Window类的实现
    • 1.4 ViewRoot类的实现
  • 02.上下文环境创建过程
    • 2.1 窗口运行环境介绍
    • 2.2 Context创建流程
    • 2.3 运行环境总结下
  • 03.窗口Window创建
    • 3.1 Activity和Window
    • 3.2 窗口Window创建过程
    • 3.3 Window显示过程
    • 3.4 Dialog中Window创建
  • 04.视图View创建
    • 4.1 视图View的介绍
    • 4.2 DecorView类实现
    • 4.3 窗口视图与ViewRoot
    • 4.4 窗口视图创建过程
  • 05.应用窗口与WMS
    • 5.1
  • 06.Surface创建过程
    • 6.1

00.问题答疑思考

  • Activity、PhoneWindow、DecorView、ViewRootImpl 之间的关系?四者的创建时机?

01.Android组件UI实现

1.1 组件的UI实现介绍

  • Activity组件的UI实现需要与WindowManagerService服务和SurfaceFlinger服务进行交互。
    • Activity组件在启动完成后,会通过一个类型为Session的Binder对象来请求WindowManagerService为它创建一个类型为WindowState的对象,用来描述它的窗口状态。
    • Android应用程序会通过一个类型为Client的Binder对象来请求SurfaceFlinger服务为它创建一个类型为Layer的对象,用来描述它的窗口数据。
  • Activity组件与WindowManagerService服务和SurfaceFlinger服务的交互模型
    • image
      image

1.2 Activity组件类关系

  • Activity组件的类关系图
    • image
      image
  • 从启动到Activity创建Window的整体流程
    • image
      image
  • Activity创建Surface流程
    • image
      image
  • Activity类与Context关系
    • Activity类是从ContextThemeWrapper类继承下来的,而ContextThemeWrapper类又是从ContextWrapper类继承下来的,最后ContextWrapper类又继承了Context类。
    • 这个ContextImpl对象首先是通过调用Activity类的成员函数attach传递到Activity组件内部,接着再依次通过调用父类ContextThemeWrapper和ContextWrapper的成员函数attachBaseContext来分别保存在它们的成员变量mBase中。
    • 因此,ContextThemeWrapper和ContextWrapper类的成员变量mBase指向的实际上是一个ContextImpl对象。
  • Activity启动是如何和Context交互的

    ActivityThread#performLaunchActivity(),创建Activity类型上下文Context然后创建activity对象 ActivityThread#createBaseContextForActivity(),通过ContextImpl静态方法创建该对象 ContextImpl#createActivityContext(),通过new去新建一个ContextImpl对象,并且做初始化配置操作

1.3 Window类的实现

  • Activity组件创建一个PhoneWindow
    • image
      image
  • PhoneWindow创建过程

    ActivityThread#performLaunchActivity(),通过反射的机制创建的Activity,并调用了Activity的attach方法 Activity#attach(),在attach方法这里初始化了一些Activity的成员变量,最重要是创建PhoneWindow对象

  • PhoneWindow类的实现说明
    • PhoneWindow类有两个重要的成员变量mDecor和mContentParent,它们的类型分别DecorView和ViewGroup。
    • 其中,成员变量mDecor是用描述自己的窗口视图,而成员变量mContentParent用来描述视图内容的父窗口。
  • DecorView类继承了FrameLayout类
    • DecorView类继承了FrameLayout类,而FrameLayout类又继承了ViewGroup类,最后ViewGroup类又继承了View类。View类有一个成员函数draw,它是用来绘制应用程序窗口的UI的。
    • DecorView类、FrameLayout类和ViewGroup类都重写了父类的成员函数draw,这样,它们就都可以定制自己的UI。
  • DecorView类所描述的应用程序窗口视图是否需要重新绘制是由另外一个类ViewRoot来控制的。
    • 系统在启动一个Activity组件的过程中,会为这个Activity组件创建一个ViewRoot对象,同时还会将前面为这个Activity组件所创建的一个PhoneWindow对象的成员变量mDecor所描述的一个视图(DecorView)保存在这个ViewRoot对象的成员变量mView中。
    • 这个ViewRoot对象就可以通过调用它的成员变量mView的所描述的一个DecorView的成员函数draw来绘制一个Activity组件的UI了。

1.4 ViewRoot类的实现

  • ViewRoot类的实现图
    • image
      image
    • ViewRoot类的作用是非常大的,它除了用来控制一个Activity组件的UI绘制之外,还负责接收Activity组件的IO输入事件,例如,键盘事件
  • ViewRoot类的创建过程

    WindowManagerImpl#addView(),在这个类中可以看到调用了mGlobal.addView(),而mGlobal是WindowManagerGlobal的对象。 WindowManagerGlobal#addView(),这里面逻辑很核心,创建ViewRootImpl对象,这个是布局渲染的核心类 WindowManagerGlobal#addView#root.setView(),实现了view与root的关联,这个root是ViewRootImpl对象

02.上下文环境创建过程

2.1 窗口运行环境介绍

  • Android应用程序窗口在运行的过程中,需要访问一些特定的资源或者类。
    • 这些特定的资源或者类构成了Android应用程序的运行上下文环境,Android应用程序窗口可以通过一个Context接口来访问它,这个Context接口也是我们在开发应用程序时经常碰到的。
  • Android应用程序窗口的运行上下文环境是通过ContextImpl类来描述的,即每一个Activity组件都关联有一个ContextImpl对象。
    • image
      image
    • Activity组件通过其父类ContextThemeWrapper和ContextWrapper的成员变量mBase来引用了一个ContextImpl对象。
    • 这样,Activity组件以后就可以通过这个ContextImpl对象来执行一些具体的操作,例如,启动Service组件、注册广播接收者和启动Content Provider组件等操作。

2.2 Context创建流程

  • Context创建流程
    • 通过ActivityThread类的成员函数performLaunchActivity在应用程序进程中创建一个Activity实例,并且为它设置运行上下文环境,即为它创建一个ContextImpl对象。
    • image
      image
  • 比较重要的流程介绍

    ActivityThread.handleLaunchActivity() ActivityThread.performLaunchActivity() mInstrumentation.newActivity 使用反射创建Activity activity.attach 这里会调用Activity中attach方法 Activity.attach() mWindow = new PhoneWindow 这里创建所属的PhoneWindow mWindow.setWindowManager 设置并获取 WindowManagerImpl 对象

  • Android应用程序窗口的运行上下文环境的创建过程
    • 第一步:ActivityThread#performLaunchActivity(),主要看mInstrumentation.newActivity()的过程。Instrumentation类是用来记录应用程序与系统的交互过程的
      • 要启动的Activity组件的类名保存在变量component。有了这个类名之后,函数就可以调用ActivityThread类的成员变量mInstrumentation所描述一个Instrumentation对象的成员函数newActivity来创建一个Activity组件实例了,并且保存变量activity中。
    • 第二步:ActivityThread#createBaseContextForActivity,这里是创建ContextImpl的步骤
      • 这里最终会调用到ContextImpl#createActivityContext,通过new创建该impl对象,且进行初始化附值操作。
    • 第三步:Instrumentation#newActivity(),这个是创建activity的过程。
      • 这里是通过ClassLoader去load具体的要加载的类的className,得到一个Class对象。
      • 由于className描述的是一个Activity子类,因此,当函数调用前面得到的Class对象的成员函数newInstance的时候,就会创建一个Activity子类实例。
    • 第四步:new Activity,第二步通过反射创建activity对象,创建对象是必须通过构造函数创建的
      • 一般来说,一个类的构造函数是用来初始化该类的实例的,系统为Activity类提供的默认构造函数什么也不做,也就是说,Activity类实例在创建的时候,还没有执行实质的初始化工作。
    • 第五步:appContext.setOuterContext(),还是在performLaunchActivity方法里面,看看做了什么
      • 即ActivityThread类的成员函数performLaunchActivity中,接下来就会调用ContextImpl类的成员函数setOuterContext来设置前面所创建一个ContextImpl对象所关联的一个Activity组件,即正在启动的Activity组件。
      • 一个ContextImpl对象所关联的一个Activity组件是通过调用ContextImpl类的成员函数setOuterContext来设置的。
      • setOuterContext只是简单地将它保存在成员变量mContext中,以表明当前正在处理的一个ContextImpl对象是用来描述一个Activity组件的运行上下文环境的。
    • 第六步:activity.attach(),这里是真正进入到Activity初始化的过程
      • 初始化一个Activity组件实例需要一个Application对象app、一个ContextImpl对象appContext以及一个Configuration对象config,它们分别用来描述该Activity组件实例的应用程序信息、运行上下文环境以及配置信息。
      • 最开始是调用Activity#attachBaseContext()方法,这个我们看下面的第七步。
      • 接着创建了一个PhoneWindow,并且保存在Activity类的成员变量mWindow中。这个PhoneWindow是用来描述当前正在启动的应用程序窗口的。
      • 这个应用程序窗口在运行的过程中,会接收到一些事件,例如,键盘、触摸屏事件等,这些事件需要转发给与它所关联的Activity组件处理,这个转发操作是通过一个Window.Callback接口来实现的。
      • 参数info指向的是一个ActivityInfo对象,用来描述当前正在启动的Activity组件的信息。其中,这个ActivityInfo对象的成员变量softInputMode用来描述当前正在启动的一个Activity组件是否接受软键盘输入。
    • 第七步:ContextThemeWrapper.attachBaseContext(),接着第六步往下分析
      • 由调用Activity#attachBaseContext()方法分析,最终会调用到ContextThemeWrapper#attachBaseConext。
      • ContextThemeWrapper类用来维护一个应用程序窗口的主题,而用来描述这个应用程序窗口的运行上下文环境的一个ContextImpl对象就保存在ContextThemeWrapper类的成员函数mBase中。
    • 第八步:ContextWrapper.attachBaseContext(),,接着第七步往下分析
      • ContextWrapper类只是一个代理类,它只是简单地封装了对其成员变量mBase所描述的一个Context对象的操作。
      • ContextWrapper类的成员函数attachBaseContext的实现很简单,它只是将参数base所描述的一个ContextImpl对象保存在成员变量mBase中。这样,ContextWrapper类就可以将它的功能交给ContextImpl类来具体实现。
    • 第九步:Instrumentation#callActivityOnCreate(),主要是执行activity的生命周期onCreate
      • 函数主要就是调用当前正在启动的Activity组件的成员函数onCreate,用来通知它已经成功地创建和启动完成了。
    • 第十步:Activity#onCreate(),这里会回调Activity的方法,也是开发的入口
      • 一般来说,我们都是通过定义一个Activity子类来实现一个Activity组件的。重写父类Activity的某些成员函数的时候,必须要回调父类Activity的这些成员函数。
      • 例如,当Activity子类在重写父类Activity的成员函数onCreate时,就必须回调父类Activity的成员函数onCreate。这些成员函数被回调了之后,Activity类就会将其成员变量mCalled的值设置为true。这样,Activity类就可以通过其成员变量mCalled来检查其子类在重写它的某些成员函数时,是否正确地回调了父类的这些成员函数。

2.3 运行环境总结下

  • 一个Activity组件的创建过程,以及它的运行上下文环境的创建过程。这个过程比较简单,我们是从中获得以下三点信息:
    • 一个Android应用窗口的运行上下文环境是使用一个ContextImpl对象来描述的,这个ContextImpl对象会分别保存在Activity类的父类ContextThemeWrapper和ContextWrapper的成员变量mBase中,即ContextThemeWrapper类和ContextWrapper类的成员变量mBase指向的是一个ContextImpl对象。
    • Activity组件在创建过程中,即在它的成员函数attach被调用的时候,会创建一个PhoneWindow对象,并且保存在成员变量mWindow中,用来描述一个具体的Android应用程序窗口。
    • Activity组件在创建的最后,即在它的子类所重写的成员函数onCreate中,会调用父类Activity的成员函数setContentView来创建一个Android应用程序窗口的视图。

03.窗口Window创建

3.1 Activity和Window

  • 在PHONE平台上,与Activity组件所关联的窗口对象的实际类型为PhoneWindow,后者是从Window类继承下来的。
    • image
      image
  • Window和PhoneWindow的类关系图。
    • image
      image
  • Window创建流程图如下所示
    • image
      image

3.2 窗口Window创建过程

  • Activity组件所关联的一个PhoneWindow对象是从Activity类的成员函数attach中创建的。
    • image
      image
  • Android应用程序窗口创建过程的源码流程分析
    • Activity#attach(),在attach方法中创建了核心的Window窗口
      • 有了这个类型为PhoneWindow的应用程序窗口,函数接下来还会调用它的成员函数setCallback、setSoftInputMode和setWindowManager来设置窗口回调接口、软键盘输入区域的显示模式和本地窗口管理器。
    • PhoneWindow#(),在构造函数中获取布局解析器
      • 首先调用父类Window的构造函数来执行一些初始化操作,接着再调用LayoutInflater的静态成员函数from创建一个LayoutInflater实例,并且保存在成员变量mLayoutInflater中。
      • PhoneWindow类以后就可以通过成员变量mLayoutInflater来创建应用程序窗口的视图,这个视图使用类型为DecorView的成员变量mDecor来描述。
      • PhoneWindow类还有另外一个类型为ViewGroup的成员变量mContentParent,用来描述一个视图容器,这个容器存放的就是成员变量mDecor所描述的视图的内容,不过这个容器也有可能指向的是mDecor本身。
    • Activity#attach()中mWindow.setCallback(this),这个是设置接口与Activity关联
      • 正在启动的Activity组件会将它所实现的一个Callback接口设置到与它所关联的一个PhoneWindow对象的父类Window的成员变量mCallback中去
      • 这样当这个PhoneWindow对象接收到系统给它分发的IO输入事件。例如,键盘和触摸屏事件,转发给与它所关联的Activity组件处理
    • Activity#attach()中mWindow.setSoftInputMode(),这个是设置输入键盘和Activity关联
      • PhoneWindow对象从父类Window继承下来的成员函数setSoftInputMode来设置应用程序窗口的软键盘输入区域的显示模式
    • Activity#attach()中mWindow.setWindowManager(),这个是本地窗口管理器和Activity关联
      • 调用前面所创建的PhoneWindow对象从父类Window继承下来的成员函数setWindowManager来设置应用程序窗口的本地窗口管理器
      • 参数appToken用来描述当前正在处理的窗口是与哪一个Activity组件关联的,它是一个Binder代理对象,引用了在ActivityManagerService这一侧所创建的一个类型为ActivityRecord的Binder本地对象。
      • 参数appName用来描述当前正在处理的窗口所关联的Activity组件的名称,这个名称会被保存在Window类的成员变量mAppName中。
      • 参数wm用来描述一个窗口管理器。从前面的调用过程可以知道, 这里传进来的参数wm的值等于null,因此,函数首先会调用WindowManagerImpl类的静态成员函数getDefault来获得一个默认的窗口管理器。有了这个窗口管理器之后,函数接着再使用它来创建一个本地窗口管理器,即一个LocalWindowManager对象,用来维护当前正在处理的应用程序窗口。
  • 分析完成一个Activity组件所关联的应用程序窗口对象的创建过程了。从分析的过程可以知道:
    • 一个Activity组件所关联的应用程序窗口对象的类型为PhoneWindow。
    • 这个类型为PhoneWindow的应用程序窗口是通过一个类型为LocalWindowManager的本地窗口管理器来维护的。
    • 这个类型为LocalWindowManager的本地窗口管理器又是通过一个类型为WindowManagerImpl的窗口管理器来维护应用程序窗口的。
    • 这个类型为PhoneWindow的应用程序窗口内部有一个类型为DecorView的视图对象,这个视图对象才是真正用来描述一个Activity组件的UI的。

3.3 Window显示过程

  • Window显示流程图如下所示。主要是讲解activity中Window显示过程
    • image
      image
  • 大概重要流程介绍

    ActivityThread.handleResumeActivity() ActivityThread.performResumeActivity() 执行到 onResume() r.activity.makeVisible() 添加视图 Activity.makeVisible()
    wm.addView 将decorView添加到Window窗口上 mDecor.setVisibility(View.VISIBLE) 设置mDecor可见

  • WindowManager的addView流程
    • WindowManager 的 addView 的具体实现在 WindowManagerImpl 中,而 WindowManagerImpl 的 addView 又会调用 WindowManagerGlobal.addView()。
  • WindowManagerGlobal.addView()
    public void addView(View view, ViewGroup.LayoutParams params,Display display, Window parentWindow) {
        ViewRootImpl root = new ViewRootImpl(view.getContext(), display);        
        view.setLayoutParams(wparams);    
        mViews.add(view);    
        mRoots.add(root);    
        mParams.add(wparams);        
        root.setView(view, wparams, panelParentView);
    }
    • 这个过程创建一个 ViewRootImpl,并将之前创建的 DecoView 作为参数传入,以后 DecoView 的事件都由 ViewRootImpl 来管理了,比如,DecoView 上添加 View,删除 View。ViewRootImpl 实现了 ViewParent 这个接口,这个接口最常见的一个方法是 requestLayout()。
    • ViewRootImpl 是个 ViewParent,在 DecoView 添加的 View 时,就会将 View 中的 ViewParent 设为 DecoView 所在的 ViewRootImpl,View 的 ViewParent 相同时,理解为这些 View 在一个 View 链上。所以每当调用 View 的 requestLayout()时,其实是调用到 ViewRootImpl,ViewRootImpl 会控制整个事件的流程。可以看出一个 ViewRootImpl 对添加到 DecoView 的所有 View 进行事件管理。

3.4 Dialog中Window创建

  • Dialog的Window创建过程?
    • 创建Window——同样是通过PolicyManager的makeNewWindow方法完成,与Activity创建过程一致
    • 初始化DecorView并将Dialog的视图添加到DecorView中——和Activity一致(setContentView),同样是通过Window.setContentView() 来实现。
    • 将DecorView添加到Window中并显示——在Dialog的show方法中,通过WindowManager将DecorView添加到Window中(mWindowManager.addView(mDecor, 1))
    • Dialog关闭时会通过WindowManager来移除DecorView:mWindowManager.removeViewImmediate(mDecor)
    • Dialog必须采用Activity的Context,因为有应用token(Application的Context没有应用token),也可以将Dialog的Window通过type设置为系统Window就不再需要token。
  • 为什么Dialog不能用Application的Context?
    • Dialog本身的Token为null,在初始化时如果是使用Application或者Service的Context,在获取到WindowManager时,获取到的token依然是null。
    • Dialog如果采用Activity的Context,获取到的WindowManager是在activity.attach()方法中创建,token指向了activity的token。
    • 因为通过Application和Service的Context将无法获取到Token从而导致失败。
  • 将DecorView添加到Window中显示
    • 和Activity一样,都是在自身要出现在前台时才会将添加Window。
    • Dialog.show() 方法:完成DecorView的显示。
    • WindowManager.remoteViewImmediate() 方法:当Dialog被dismiss时移除DecorView。

04.视图View创建

4.1 视图View的介绍

  • 每一个Activity组件都有一个关联的Window对象,用来描述一个应用程序窗口。
    • 每一个应用程序窗口内部又包含有一个View对象,用来描述应用程序窗口的视图。应用程序窗口视图是真正用来实现UI内容和布局的,每一个Activity组件的UI内容和布局都是通过与其所关联的一个Window对象的内部的一个View对象来实现的。
    • 应用程序窗口内部所包含的视图对象的实际类型为DecorView。DecorView类继承了View类,是作为容器(ViewGroup)来使用的。

4.2 DecorView类实现

  • DecorView类的实现的流程图
    • image
      image

4.3 窗口视图与ViewRoot

  • 窗口视图与ViewRoot流程图
    • 每一个应用程序窗口的视图对象都有一个关联的ViewRoot对象,这些关联关系是由窗口管理器来维护的。
    • image
      image
  • 简单来说,ViewRoot相当于是MVC模型中的Controller,它有以下职责:
    • 1.负责为应用程序窗口视图创建Surface。
    • 2.配合WindowManagerService来管理系统的应用程序窗口。
    • 3.负责管理、布局和渲染应用程序窗口视图的UI。
  • 应用程序窗口的视图对象及其所关联的ViewRoot对象是什么时候开始创建的呢?
    • Activity组件在启动的时候,系统会为它创建窗口对象(Window),同时,系统也会为这个窗口对象创建视图对象。
    • 另一方面,当Activity组件被激活的时候,系统如果发现与它的应用程序窗口视图对象所关联的ViewRoot对象还没有创建,那么就会先创建这个ViewRoot对象,以便接下来可以将它的UI渲染出来。

4.4 窗口视图创建过程

  • 分析应用程序窗口的视图对象及其所关联的ViewRoot对象的创建过程
    • image
      image
  • 应用程序窗口视图的创建过程
    • Activity组件在启动的过程中,会调用ActivityThread类的成员函数handleLaunchActivity,用来创建以及首次激活Activity组件,因此,接下来就从这个函数开始,具体分析应用程序窗口的视图对象及其所关联的ViewRoot对象的创建过程。

    ActivityThread#handleLaunchActivity(),调用ActivityThread类的成员函数performLaunchActivity来创建要启动的Activity组件。 ActivityThread#performLaunchActivity(),它主要就是创建一个Activity组件实例,并且调用这个Activity组件实例的成员函数onCreate来让其执行一些自定义的初始化工作。 Activity#onCreate(),在实现一个Activity组件的时候,一般都会重写成员函数onCreate,以便可以执行一些自定义的初始化工作,其中就包含初始化UI的工作。 Activity#setContentView(),首先调用另外一个成员函数getWindow来获得成员变量mWindow(指向PhoneWindow)所描述的一个窗口对象,接着再调用这个窗口对象的成员函数setContentView来执行创建应用程序窗口视图对象的工作。 PhoneWindow#setContentView(),成员变量mContentParent(指DecorView的视图对象),当它等于null,就会调用成员函数installDecor来创建应用程序窗口视图对象。最后还会调用一个Callback接口的成员函数onContentChanged来通知对应的Activity组件,它的视图内容发生改变。 PhoneWindow#installDecor(),当mDecor等于null,调用成员函数generateDecor创建一个DecorView对象,并且保存在PhoneWindow类的成员变量mDecor中。

    • ActivityThread类的成员函数handleLaunchActivity中,接下来就会调用ActivityThread类的另外一个成员函数handleResumeActivity来激活正在启动的Activity组件。

    ActivityThread#handleResumeActivity(),首先调用另外一个成员函数performResumeActivity来通知Activity组件,它要被激活了,即会导致Activity组件的成员函数onResume被调用。 handleResumeActivity#r.activity.getWindow(),getWindow返回给调用者的是一个PhoneWindow对象 handleResumeActivity#r.activity.getDecorView(),通过getDecorView来获得当前正在激活的Activity组件所关联的一个应用程序窗口视图对象 handleResumeActivity#a.getWindowManager(),调用当前正在激活的Activity组件的成员函数getWindowManager来获得一个本地窗口管理器。 handleResumeActivity#wm.addView(decor, l),addView来为当前正在激活的Activity组件的应用程序窗口视图对象关联一个ViewRoot对象。 WindowManagerGlobal#addView(),这个里面会创建ViewRootImpl对象,一个View对象在与一个ViewRoot对象关联的同时,还会关联一个WindowManager.LayoutParams对象,这个WindowManager.LayoutParams对象是用来描述应用程序窗口视图的布局属性的。 WindowManagerGlobal#addView#root.setView,将这个View对view象和这个WindowManager.LayoutParams对象,以及变量panelParentView所描述的一个父应用程序窗视图对象,保存在这个ViewRoot对象root的内部 ViewRootImpl#setView(),调用requestLayout来请求对应用程序窗口视图的UI作第一次布局。调用静态成员变量sWindowSession所描述的一个类型为Session的Binder代理对象的成员函数add来请求WindowManagerService增加一个WindowState对象,以便可以用来描述当前正在处理的一个ViewRoot所关联的一个应用程序窗口。

05.应用窗口与WMS

  • https://www.kancloud.cn/alex_wsc/androids/473773

06.Surface创建过程

  • https://www.kancloud.cn/alex_wsc/androids/473774
贡献者: yangchong211
上一篇
05.Android程序UI框架
下一篇
07.WMS机制深入分析