Android Framework学习二:Activity创建及View绘制流程

文章目录

Window绘制流程

在安卓系统中,Window Manager Service(WMS)和 Surface 是与窗口管理和图形显示相关的重要概念。

Window Manager Service(WMS)

  • 功能概述:WMS 是安卓系统中负责管理窗口的系统服务。它主要负责窗口的创建、销毁、布局、显示顺序以及与用户交互等方面的管理。
  • 工作原理:当一个应用程序创建一个窗口(例如 Activity 的界面)时,它会向 WMS 发送请求。WMS 会为该窗口分配一个唯一的标识,并根据窗口的属性(如大小、位置、层级等)将其添加到窗口管理列表中。在绘制窗口时,WMS 会协调各个窗口的位置和显示顺序,确保它们按照正确的方式显示在屏幕上。当用户进行触摸屏幕等交互操作时,WMS 会根据触摸事件的位置和窗口的布局,将事件分发给相应的窗口进行处理。

Surface

  • 概念:Surface 是安卓图形系统中的一个重要概念,它代表了一个可绘制的区域,用于在屏幕上显示图形内容。可以将 Surface 看作是一块画布,应用程序可以在上面绘制各种图形、图像和文本等内容。
  • 作用:每个窗口都有一个或多个 Surface 与之关联。当应用程序需要绘制窗口的内容时,它会通过 Surface 来获取绘图的上下文,然后使用图形库(如 OpenGL)在 Surface 上进行绘制。绘制完成后,Surface 会将绘制的结果提交给系统的图形合成器(通常是 Surface Flinger),由图形合成器将各个窗口的 Surface 进行合成,最终显示在屏幕上。
  • 与 WMS 的关系:WMS 负责管理窗口的整体布局和显示顺序,而 Surface 则是窗口内容绘制的载体。WMS 会根据窗口的状态和用户的操作,通知应用程序更新其 Surface 的内容。例如,当窗口大小发生变化时,WMS 会通知应用程序重新绘制 Surface 以适应新的大小。同时,WMS 也会与 Surface Flinger 协作,确保各个 Surface 能够按照正确的顺序和方式进行合成和显示。

SurfaceFlinger

SurfaceFlinger是 Android 系统中的一个关键服务,主要负责将不同应用程序的 2D、3D surface 进行组合,并将最终合成的图像发送到显示设备进行显示。

安卓View层次结构

Activity包含PhoneWindow、DecorView、ViewRootImpl等

Activity

Activity属于安卓应用程序的四大组件之一,它为用户提供了一个可视化的界面,让用户能够与应用进行交互。每一个Activity都代表着一个屏幕画面,像是登录界面、主界面等。

在安卓中,Activity是由ActivityManagerService(AMS,活动管理器服务) 创建的 。

以下是Activity的一个简单示例:

java 复制代码
import android.app.Activity;
import android.os.Bundle;

public class MainActivity extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }
}

PhoneWindow

PhoneWindow是Window类的具体实现,Window类在安卓系统里代表着一个顶级的视觉容器,它负责管理窗口的样式、背景以及标题栏等。PhoneWindow主要处理窗口的具体显示逻辑,例如设置窗口的背景、标题栏、内容视图等。

Activity与PhoneWindow两者之间的关系

  • 包含关系:Activity包含一个PhoneWindow对象,在Activity的创建过程中,会默认创建一个PhoneWindow对象。
  • 视图关联:Activity通过PhoneWindow来设置和管理其视图。Activity的setContentView()方法实际上是调用了PhoneWindow的setContentView()方法。
java 复制代码
// Activity类中的setContentView方法
@Override
public void setContentView(@LayoutRes int layoutResID) {
    getWindow().setContentView(layoutResID);
    initWindowDecorActionBar();
}

Activity是用户交互的界面载体,负责处理用户的操作和业务逻辑;PhoneWindow则是窗口的具体实现,负责窗口的显示和管理。它们紧密协作,共同构成了安卓应用程序的用户界面。

ViewRootImpl

  • 概述:ViewRootImpl是View与WindowManager之间的桥梁,它不是一个真正的View,但它管理着一个View树的根节点,在Android系统中,每个Window都对应着一个ViewRootImpl实例。
    作用
  • 视图绘制管理:负责协调View树的绘制过程,包括测量(measure)、布局(layout)和绘制(draw)三个阶段。它会根据屏幕的刷新频率,通过Choreographer来触发视图的重绘,确保界面能够及时更新。
  • 事件分发:接收系统传递的输入事件,如触摸事件、按键事件等,并将这些事件分发给View树中的各个View进行处理。它是事件从系统到应用View的重要传递环节。
  • 与窗口管理器交互:与WindowManagerService(WMS)进行通信,负责处理窗口的创建、销毁、大小调整等操作。例如,当Activity启动时,ViewRootImpl会与WMS交互来创建窗口,并将DecorView添加到窗口中。

DecorView

在 Android 系统中,DecorView 是窗口(Window)的最顶层视图(顶级 ViewGroup),它作为整个窗口的根视图,包含了系统的装饰(如状态栏、导航栏)和应用程序的内容视图(如 Activity 的布局)。

DecorView 的作用

  • 窗口的根容器:每个 Activity 的窗口(PhoneWindow)都包含一个 DecorView,它是 View 层级的最顶层。
  • 管理系统 UI:DecorView 负责处理系统窗口装饰(如状态栏、ActionBar/Toolbar)和应用程序内容的协调。
  • 内容视图的父容器:开发者通过 setContentView() 设置的布局会被添加到 DecorView 的一个子 ViewGroup(通常是 FrameLayout,ID 为 android.R.id.content)中。

DecorView 的结构

DecorView是每个Activity界面的顶层视图,它是一个FrameLayout。

DecorView 通常包含以下两部分:

  • 系统装饰部分
    状态栏(Status Bar)、导航栏(Navigation Bar)等系统 UI。
    由主题(Theme)控制是否显示(如全屏模式会隐藏系统装饰)。
  • 应用内容部分
    通过 setContentView() 设置的布局会被添加到 android.R.id.content 这个子 FrameLayout 中。

总结

DecorView 是 Android 窗口系统的核心组件,作为连接系统 UI 和应用内容的桥梁。理解它的结构和功能有助于处理全屏、键盘交互、窗口属性等高级场景。实际开发中,通常只需通过 setContentView() 操作内容部分,而无需直接操作 DecorView。

Activity创建流程

Activity中AMS创建的。

  • window的初始化是在 Acticity 创建的时候初始化, 在Acticity对象创建后,会调用attach方法,Windows对象就是这个时候创建的。
  • Activity的setContentView其实调用的是PhoneWindow的setContentView。
  • setContentView中调用installDecor()进行DecorView的初始化。
  • onResume中会调用WindowMangerImpl的addView, ViewRootImpl就是在这个addView中创建的。
  • addView会调用ViewRootImpl的setView,setView调用WMS的addView并调用requestLayout。
  • requestLayout调用scheduleTraversals(会创建surface),scheduleTraversals调用见下段invalidate流程后段会有讲到主要是调用measure,layout,draw。

如下图为addView流程

View invalidate调用流程

  1. 起始调用
    当我们希望重绘某个View时,直接调用其invalidate方法 。比如在自定义View的事件处理方法(如onClick) 或者数据更新逻辑中调用。invalidate方法会转而调用invalidate(true) ,这里的参数表示是否同时使绘图缓存无效,一般全量刷新时为true。
  2. invalidateInternal方法
    invalidate(true)会调用invalidateInternal方法,此方法会进行以下操作:
    判断是否需要重绘:调用skipInvalidate方法判断该View是否不需要重绘,不需要重绘的条件是该View不可见并且未进行动画。
  • 处理重绘标志位:进一步判断View是否需要绘制,如判断表达式(mPrivateFlags & (DRAWN | HAS_BOUNDS)) == (DRAWN | HAS_BOUNDS) ,若满足重绘条件,则处理相关标志位,将当前View标记为 "脏" ,即设置mPrivateFlags中的相关标志,表明该View需要重绘。
  • 确定重绘区域:对于开启硬件加速的应用程序,调用父视图的invalidateChild函数绘制整个区域;否则只绘制指定的dirty区域(r变量所指区域)。这是一个向上回溯的过程,每一层的父View都将自己的显示区域与传入的刷新Rect做交集。
  1. ViewGroup中的调用
  • invalidateChild方法:在ViewGroup中,invalidateChild方法会从当前的布局View向上不断遍历其父布局。它会先处理子View重绘相关逻辑,比如根据子View情况设置一些标志位,然后调用父布局的invalidateChildInParent方法。
  • invalidateChildInParent方法:该方法会计算需要重绘的区域 ,涉及到location数组(表示自身左边、上边距离父组件的距离,确立在坐标系的相对位置 )和dirty矩形(包含自身宽高,确立需要重绘的面积大小 )。计算后会继续向上请求父布局重绘,直到父布局为ViewRootImpl 。
  1. ViewRootImpl中的处理
  • invalidateChildInParent方法:ViewRootImpl中的invalidateChildInParent方法会检查线程是否正确 ,若dirty为null,表示要重绘整个区域,直接调用invalidate;若dirty为空且没有动画,就不需要重绘,直接返回。否则会对重绘区域进行进一步处理,如根据滚动偏移等情况调整区域。
  • invalidate方法:调用invalidate方法后,会通过scheduleTraversals方法安排一次视图遍历。
  1. 视图遍历与绘制
  • scheduleTraversals方法:安排视图遍历工作,将任务添加到消息队列,待合适时机(比如下一次绘制周期 )执行。
  • performTraversals方法:视图遍历的核心方法,依次执行测量(performMeasure ,调用measure ,最终到onMeasure )、布局(performLayout ,调用layout ,最终到onLayout )、绘制(performDraw ,调用draw ,最终到onDraw )等步骤 ,完成整个View树的更新绘制 。其中performDraw会进一步调用drawSoftware ,最终触发View的draw方法,开始实际绘制。

    Android Framework学习一:系统框架、启动过程
    Android Framework学习二:Activity创建及View绘制流程
    作者:帅得不敢出门
相关推荐
知识分享小能手23 分钟前
React学习教程,从入门到精通, React 入门指南:React JSX 语法知识点详解及案例代码(8)
前端·javascript·vue.js·学习·react.js·前端框架·anti-design-vue
张较瘦_1 小时前
[论文阅读] 软件工程 | 告别“线程安全玄学”:基于JMM的Java类静态分析,CodeQL3分钟扫遍GitHub千仓错误
java·论文阅读·安全
A尘埃3 小时前
智慧零售全渠道业务中台系统
java·零售
翻滚丷大头鱼4 小时前
android View详解—View的刷新流程源码解析
android
zhangphil5 小时前
Android adb shell命令分析应用内存占用
android·adb
二向箔reverse5 小时前
深度学习中的学习率优化策略详解
人工智能·深度学习·学习
悠哉悠哉愿意5 小时前
【机器学习学习笔记】线性回归实现与应用
笔记·学习·机器学习
漠缠6 小时前
Android AI客户端开发(语音与大模型部署)面试题大全
android·人工智能
小wanga7 小时前
C++知识
java·开发语言·c++