在上篇文章中,我们通过跟踪源码,我们了解了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. django----数据库表设计

    设计表时注意的几点: 1. nid = models.AutoField(primary_key=True)        #如果不指定django会默认加上id的 nid = models.BigA ...

  2. 【APUE | 7】命令形参、函数

    命令形参 命令行参数是使用main()函数参数来处理的,其中,argc是指传入参数的个数,argv[]是一个指针数组,指向传递给程序的每个参数. 应当指出的是, argv[0]存储程序的名称,argv ...

  3. [转] SSO单点登录原理和流程分析

    WEB的登录那些事#### 说道账户登录和注册,其实我们每天都在亲身感受着,像微博.知乎还有简书等等.我们总是需要定期的去重新登录一下,对于这种认证机制,我们都能说出来两个名词,Cookie.Sess ...

  4. openstack安装-计算节点-nova计算服务安装

    一.基础服务安装 先安装基础工具 yum install net-tools vim telnet wget lrzsz 1.添加hosts解析 cat << EOF >/etc/h ...

  5. ubuntu TensorFlow安装

    Tensorflow安装确实比caffe简单... cuda,cudnn安装就不说了 1 安裝pip(有就跳过) sudo apt-get install python-pip python-dev ...

  6. python的pickle和shelve模块

    python中用于序列化的模块总结 目录 pickle模块 shelve模块 xml模块 pickle模块 介绍 Pickle的问题和所有其他编程语言特有的序列化问题一样,就是它只能用于Python, ...

  7. Python图形编程探索系列-08-再次认识标签

    标签的各种属性 代码展示: import tkinter as tk root = tk.Tk() root.geometry = '500x300' label1 = tk.Label(root, ...

  8. 潭州课堂25班:Ph201805201 爬虫基础 第七课 Python与常见加密方式 (课堂笔记)

    打开图形界面  18版 Python与常见加密方式 前言 我们所说的加密方式,都是对二进制编码的格式进行加密的,对应到Python中,则是我们的Bytes. 所以当我们在Python中进行加密操作的时 ...

  9. c/c++中int main(int argc,char *argv[])的具体含义

    int main(int argc,char * argv[ ]) argv为指针的指针 argc为整数 char **argv or: char *argv[ ] or: char argv[ ][ ...

  10. 关于Android studio团队协同开发连接到已有项目

    当团队中已经有人创建好项目的时候,队员想把自己的as与码云上项目相互连接时,有两种方法: 方法一: 进入as初始页面: 分别点击:check out project from Version cont ...