在上篇文章中,我们通过跟踪源码,我们了解了Activity、Window、DecorView以及View之间的关系(查看文章:http://www.cnblogs.com/jerehedu/p/4607599.html#gui)。那么整个Activity的界面到底是如何绘制出来的呢?既然DecorView作为Activity的顶层界面视图,那么整个界面的绘制工作应该从它开始,下面我们继续跟踪源码,看看是不是这样的。

  Activity在启动过程中会调用主线程ActivityThread中的方法performLaunchActivity和handleResumeActivity。在方法handleResumeActivity中会将创建的DecorView和WindowManagerImpl对象关联起来,关键源码部分如下:

public final class ActivityThread {
……
final void handleResumeActivity(IBinder token,
boolean clearHide, boolean isForward, boolean reallyResume) {
……
if (r.window == null && !a.mFinished && willBeVisible) {
r.window = r.activity.getWindow();
View decor = r.window.getDecorView();
decor.setVisibility(View.INVISIBLE);
ViewManager wm = a.getWindowManager();
WindowManager.LayoutParams l = r.window.getAttributes();
a.mDecor = decor;
l.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
l.softInputMode |= forwardBit;
if (a.mVisibleFromClient) {
a.mWindowAdded = true;
wm.addView(decor, l);
} }
……
}
}

  WindowManagerImpl关键代码:

    public final class WindowManagerImpl implements WindowManager {
private final WindowManagerGlobal mGlobal = WindowManagerGlobal.getInstance();
……
@Override
public void addView(View view, ViewGroup.LayoutParams params) {
mGlobal.addView(view, params, mDisplay, mParentWindow);
}
……
}

  WindowManagerGlobal关键代码:

public final class WindowManagerGlobal {
……
public void addView(View view, ViewGroup.LayoutParams params,
Display display, Window parentWindow) {
……
ViewRootImpl root;
View panelParentView = null;
……
root.setView(view, wparams, panelParentView);
……
}
}

  根据源码调用关系,可得下图:

  从图中,我们可以看出在ActivityThread中生成的DecorView经过WindowManagerImpl、WindowManagerGlobal,最终调用了ViewRootImpl中的setView方法,将DecorView设置赋值给了ViewRootImpl中的mView属性。通过追踪ViewRootImpl我们发现最终调用了performTraversals方法,该方法关键代码如下:

private void performTraversals() {
// cache mView since it is used so much below...
final View host = mView;
……
performMeasure(childWidthMeasureSpec, childHeightMeasureSpec);
……
performLayout(lp, desiredWindowWidth, desiredWindowHeight);
……
performDraw();
……
}

  从上述源码中我们可以看出,performTraversals实际上依次调用了三个关键的方法,分别是performMeasure,performLayout、performDraw。

  1、方法performMeasure,内部实际上调用了mView.measure(childWidthMeasureSpec, childHeightMeasureSpec);不要忘了此处的mView正是我们传递进来的DecorView,该方法用于测量View的大小。关键源码如下:

        private void performMeasure(int childWidthMeasureSpec, int childHeightMeasureSpec) {
Trace.traceBegin(Trace.TRACE_TAG_VIEW, "measure");
try {
mView.measure(childWidthMeasureSpec, childHeightMeasureSpec);
} finally {
Trace.traceEnd(Trace.TRACE_TAG_VIEW);
}
}

  2、方法performLayout,内部实际上调用了host.layout(0, 0, host.getMeasuredWidth(), host.getMeasuredHeight());该方法用于确定视图的位置。关键源码如下:

    private void performLayout(WindowManager.LayoutParams lp, int desiredWindowWidth,
int desiredWindowHeight) {
mLayoutRequested = false;
mScrollMayChange = true;
mInLayout = true; final View host = mView;
……
try {
host.layout(0, 0, host.getMeasuredWidth(), host.getMeasuredHeight()); mInLayout = false;
int numViewsRequestingLayout = mLayoutRequesters.size();
if (numViewsRequestingLayout > 0) {
……
if (validLayoutRequesters != null) {
// Set this flag to indicate that any further requests are happening during
……
host.layout(0, 0, host.getMeasuredWidth(), host.getMeasuredHeight()); ……
}
} }
} finally {
Trace.traceEnd(Trace.TRACE_TAG_VIEW);
}
mInLayout = false;
}

  3、方法performDraw,用于绘制视图,追踪源码发现,最终调用了mView.draw(canvas)方法,用于绘制。

  经过上述过程基本上可以确定View的绘制流程,流程图具体如下:

  疑问咨询或技术交流,请加入官方QQ群: (452379712)

作者:杰瑞教育
出处:http://www.cnblogs.com/jerehedu/ 
本文版权归烟台杰瑞教育科技有限公司和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
 

Android GUI之View绘制流程的更多相关文章

  1. Android面试,View绘制流程以及invalidate()等相关方法分析

    整个View树的绘图流程是在ViewRoot.java类的performTraversals()函数展开的,该函数做的执行过程可简单概况为 根据之前设置的状态,判断是否需要重新计算视图大小(measu ...

  2. Android应用层View绘制流程与源码分析

    1  背景 还记得前面<Android应用setContentView与LayoutInflater加载解析机制源码分析>这篇文章吗?我们有分析到Activity中界面加载显示的基本流程原 ...

  3. 【朝花夕拾】Android自定义View篇之(一)View绘制流程

    前言 转载请申明转自[https://www.cnblogs.com/andy-songwei/p/10955062.html]谢谢! 自定义View.多线程.网络,被认为是Android开发者必须牢 ...

  4. 1.Android 视图及View绘制分析笔记之setContentView

    自从1983年第一台图形用户界面的个人电脑问世以来,几乎所有的PC操作系统都支持可视化操作,Android也不例外.对于所有Android Developer来说,我们接触最多的控件就是View.通常 ...

  5. View绘制流程

    1. View 树的绘图流程 当 Activity 接收到焦点的时候,它会被请求绘制布局,该请求由 Android framework 处理.绘制是从根节点开始,对布局树进行 measure 和 dr ...

  6. 【view绘制流程】理解

    一.概述 View的绘制是从上往下一层层迭代下来的.DecorView-->ViewGroup(--->ViewGroup)-->View ,按照这个流程从上往下,依次measure ...

  7. 公共技术点( View 绘制流程)

    转载地址:http://p.codekk.com/blogs/detail/54cfab086c4761e5001b253f 本文为 Android 开源项目源码解析 公共技术点中的 View 绘制流 ...

  8. 【转载】Android 中 View 绘制流程分析

    创建Window 在Activity的attach方法中通过调用PolicyManager.makeNewWindo创建Window,将一个View add到WindowManager时,Window ...

  9. Android中View绘制流程以及invalidate()等相关方法分析

    [原文]http://blog.csdn.net/qinjuning 整个View树的绘图流程是在ViewRoot.java类的performTraversals()函数展开的,该函数做的执行过程可简 ...

随机推荐

  1. CCF2014032窗口(C语言)

    问题描述 在某图形操作系统中,有 N 个窗口,每个窗口都是一个两边与坐标轴分别平行的矩形区域.窗口的边界上的点也属于该窗口.窗口之间有层次的区别,在多于一个窗口重叠的区域里,只会显示位于顶层的窗口里的 ...

  2. PHP实现中文字符串截取无乱码

    在我们学习PHP知识的过程中,PHP截取字符串应该是一个非常常见的字符串基础操作了,想必大家都比较熟悉这方面知识点. 但是有些新手朋友们可能遇到过,当截取中英文字符串时出现乱码的情况,其实这个也是非常 ...

  3. iOS学习笔记之Block

    写在前面 学习iOS开发的过程中,在很多场合都遇到了Block.说实话,虽然自己依葫芦画瓢的将Block"拿来"用着,但这种"拿来主义"与学习时应持有的探索精神 ...

  4. 2018-2019 2 20165203 《网络对抗技术》 Exp2 后门原理与实践

    2018-2019 2 20165203 <网络对抗技术> Exp2 后门原理与实践 实验内容 1.使用netcat获取主机操作Shell,cron启动 (0.5分) 2.使用socat获 ...

  5. 【C++】三大概念要分清--重载,隐藏(重定义,覆盖(重写)

    { c++三大概念要分清--重载,隐藏(重定义),覆盖(重写)} 重载 •  概念:在同一个作用域内:函数名相同,参数列表不同(参数个数不同,或者参数类型不同,或者参数个数和参数类型都不同),返回值类 ...

  6. CentOS6.8安装360 pika

    1.安装依赖包 yum install snappy-devel bz2 libzip-dev libsnappy-dev libprotobuf-dev libevent-dev protobuf- ...

  7. BZOJ1295 [SCOI2009]最长距离 最短路 SPFA

    欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ1295 题意概括 有一块矩形土地,被分为 N*M 块 1*1 的小格子. 有的格子含有障碍物. 如果 ...

  8. drupal笔记

    $app_root :网站根目录 安装 汉化:1将汉化包放置drupal8\sites\default\files\translations下安装:2极简版的话需要在extend(扩展)中安装Inte ...

  9. macos 下通过sublime text 3 + gosublime+sublimegdb 开发注意事项

    1.macos系统10.13.4下 安装gdb8.0可以正常调试,而gdb8.1不能正常调试,需要跳过这个坑 2.需要对gdb 8.0进行软件签名 3.通过gosublime 运行(cmd+b),添加 ...

  10. SpringBoot+Mybatis多模块(module)项目搭建教程

    一.前言 最近公司项目准备开始重构,框架选定为SpringBoot+Mybatis,本篇主要记录了在IDEA中搭建SpringBoot多模块项目的过程. 1.开发工具及系统环境 IDE:Intelli ...