分析之前先了解下View的绘制流程

首先view在windows中的布局样式如下图:

view绘制在windows,windows与DecoverView的交互在VIewRoot中进行。

view绘制的入口函数是ViewRootImpl中的performTraversals, performTraversals钟会一次调用performMeasure、performLayout、performDraw,三个函数中会分别调用view.Measure、view.Layout、view.Draw,然后分别调用需要子类实现的onMeasure、onLayout、onDraw函数。

而继承自view的自定义view或者系统写好的textview或者LinearLayout等实例化的onMeasure、onLayout、onDraw函数分别用于测量view大小,摆放view、以及将view画出来。

LinearLayout继承自viewGroup,在onMeasure中,会分别调用子控件的view.Measure, 进而在子控件的onMeasur中完成测量,如果子控件仍然是一个viewGroup则依次下去。

view绘制各重载函数的执行流程:

      1、android:visibility=visible

创建
I/TestView: TestView(Context context, AttributeSet attrs)
I/TestView: onFinishInflate()
I/TestView: onVisibilityChanged(View changedView, int visibility) changedView = com.android.internal.policy.impl.PhoneWindow$DecorView{2192bad9 I.E..... R.....ID 0,0-0,0} visibility = 4
I/TestView: onVisibilityChanged(View changedView, int visibility) changedView = com.android.internal.policy.impl.PhoneWindow$DecorView{2192bad9 V.E..... R.....ID 0,0-0,0} visibility = 0
I/TestView: onAttachedToWindow()
I/TestView: onWindowVisibilityChanged(int visibility) visibility = 0
I/TestView: onMeasure(int widthMeasureSpec, int heightMeasureSpec) widthMeasureSpec = 1073743152 heightMeasureSpec = 1073743848
I/TestView: onMeasure(int widthMeasureSpec, int heightMeasureSpec) widthMeasureSpec = 1073743152 heightMeasureSpec = 1073743848
I/TestView: onMeasure(int widthMeasureSpec, int heightMeasureSpec) widthMeasureSpec = 1073743152 heightMeasureSpec = 1073744016
I/TestView: onMeasure(int widthMeasureSpec, int heightMeasureSpec) widthMeasureSpec = 1073743152 heightMeasureSpec = 1073744016
I/TestView: onSizeChanged(int w, int h, int oldw, int oldh) w = 1328 h = 2192 oldw = 0 oldh0
I/TestView: onLayout(boolean changed, int left, int top, int right, int bottom) changed = true left = 56 top = 56 right = 1384 bottom = 2248
I/TestView: onMeasure(int widthMeasureSpec, int heightMeasureSpec) widthMeasureSpec = 1073743152 heightMeasureSpec = 1073743820
I/TestView: onSizeChanged(int w, int h, int oldw, int oldh) w = 1328 h = 1996 oldw = 1328 oldh2192
I/TestView: onLayout(boolean changed, int left, int top, int right, int bottom) changed = true left = 56 top = 56 right = 1384 bottom = 2052
I/TestView: onDraw(Canvas canvas)
I/TestView: onWindowFocusChanged(boolean hasWindowFocus) hasWindowFocus = true
I/TestView: onMeasure(int widthMeasureSpec, int heightMeasureSpec) widthMeasureSpec = 1073743152 heightMeasureSpec = 1073743820
I/TestView: onMeasure(int widthMeasureSpec, int heightMeasureSpec) widthMeasureSpec = 1073743152 heightMeasureSpec = 1073743820
I/TestView: onLayout(boolean changed, int left, int top, int right, int bottom) changed = false left = 56 top = 56 right = 1384 bottom = 2052
I/TestView: onDraw(Canvas canvas)
销毁
I/TestView: onWindowFocusChanged(boolean hasWindowFocus) hasWindowFocus = false
I/TestView: onWindowVisibilityChanged(int visibility) visibility = 8
I/TestView: onDetachedFromWindow()

2、android:visibility=invisible

创建
I/TestView: onVisibilityChanged(View changedView, int visibility) changedView = com.example.junyizhou.rxjavademo.TestView{3ead3d52 I.ED.... ........ 0,0-0,0} visibility = 4
I/TestView: TestView(Context context, AttributeSet attrs)
I/TestView: onFinishInflate()
I/TestView: onVisibilityChanged(View changedView, int visibility) changedView = com.android.internal.policy.impl.PhoneWindow$DecorView{3aeb2b95 I.E..... R.....ID 0,0-0,0} visibility = 4
I/TestView: onVisibilityChanged(View changedView, int visibility) changedView = com.android.internal.policy.impl.PhoneWindow$DecorView{3aeb2b95 V.E..... R.....ID 0,0-0,0} visibility = 0
I/TestView: onAttachedToWindow()
I/TestView: onWindowVisibilityChanged(int visibility) visibility = 0
I/TestView: onMeasure(int widthMeasureSpec, int heightMeasureSpec) widthMeasureSpec = 1073743152 heightMeasureSpec = 1073743848
I/TestView: onMeasure(int widthMeasureSpec, int heightMeasureSpec) widthMeasureSpec = 1073743152 heightMeasureSpec = 1073743848
I/TestView: onMeasure(int widthMeasureSpec, int heightMeasureSpec) widthMeasureSpec = 1073743152 heightMeasureSpec = 1073744016
I/TestView: onMeasure(int widthMeasureSpec, int heightMeasureSpec) widthMeasureSpec = 1073743152 heightMeasureSpec = 1073744016
I/TestView: onSizeChanged(int w, int h, int oldw, int oldh) w = 1328 h = 2192 oldw = 0 oldh0
I/TestView: onLayout(boolean changed, int left, int top, int right, int bottom) changed = true left = 56 top = 56 right = 1384 bottom = 2248
I/TestView: onMeasure(int widthMeasureSpec, int heightMeasureSpec) widthMeasureSpec = 1073743152 heightMeasureSpec = 1073743820
I/TestView: onSizeChanged(int w, int h, int oldw, int oldh) w = 1328 h = 1996 oldw = 1328 oldh2192
I/TestView: onLayout(boolean changed, int left, int top, int right, int bottom) changed = true left = 56 top = 56 right = 1384 bottom = 2052
I/TestView: onWindowFocusChanged(boolean hasWindowFocus) hasWindowFocus = true
I/TestView: onMeasure(int widthMeasureSpec, int heightMeasureSpec) widthMeasureSpec = 1073743152 heightMeasureSpec = 1073743820
I/TestView: onMeasure(int widthMeasureSpec, int heightMeasureSpec) widthMeasureSpec = 1073743152 heightMeasureSpec = 1073743820
I/TestView: onLayout(boolean changed, int left, int top, int right, int bottom) changed = false left = 56 top = 56 right = 1384 bottom = 2052
销毁
I/TestView: onWindowFocusChanged(boolean hasWindowFocus) hasWindowFocus = false
I/TestView: onWindowVisibilityChanged(int visibility) visibility = 8
I/TestView: onDetachedFromWindow()

3、android:visibility=gone

创建

I/TestView: onVisibilityChanged(View changedView, int visibility) changedView = com.example.junyizhou.rxjavademo.TestView{3ead3d52 G.ED.... ......I. 0,0-0,0} visibility = 8
I/TestView: TestView(Context context, AttributeSet attrs)
I/TestView: onFinishInflate()
I/TestView: onVisibilityChanged(View changedView, int visibility) changedView = com.android.internal.policy.impl.PhoneWindow$DecorView{3aeb2b95 I.E..... R.....ID 0,0-0,0} visibility = 4
I/TestView: onVisibilityChanged(View changedView, int visibility) changedView = com.android.internal.policy.impl.PhoneWindow$DecorView{3aeb2b95 V.E..... R.....ID 0,0-0,0} visibility = 0
I/TestView: onAttachedToWindow()
I/TestView: onWindowVisibilityChanged(int visibility) visibility = 0
I/TestView: onWindowFocusChanged(boolean hasWindowFocus) hasWindowFocus = true

销毁

I/TestView: onWindowFocusChanged(boolean hasWindowFocus) hasWindowFocus = false I/TestView: onWindowVisibilityChanged(int visibility) visibility = 8 I/TestView: onDetachedFromWindow()

下面比较下LinearLayout和RelativeLayout的性能

一个实现垂直列表的布局测试数据如下:

LinearLayout

Measure:0.738ms
Layout:0.176ms
draw:7.655ms

RelativeLayout

Measure:2.280ms
Layout:0.153ms
draw:7.696ms

考虑到误差,两者layout和draw几乎差不多,主要区别在于Measure。

1、分析源码发现,在RelativeLayout中,由于布局可以是B横向依赖A,A横向依赖B, 所以,Measure中会被Measure两次,一次是横向的Measure,一次是纵向。

而在LinearLayout中,在测量之前就判断了是横向还是纵向布局。

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
if (mOrientation == VERTICAL) {
measureVertical(widthMeasureSpec, heightMeasureSpec);
} else {
measureHorizontal(widthMeasureSpec, heightMeasureSpec);
}
}

2、但是在Linearlayout中如果设置weight会影响性能,因为LinearLayout会避开设置过weight属性的view做第一次measure,完了再对设置过weight属性的view做第二次measure。

3、view中的Measure有个优化,但是如果RelativeLayout中设置的margin就会跳过这个优化,多以尽量使用padding而不是margin。

4、

.在不影响层级深度的情况下,使用LinearLayout和FrameLayout而不是RelativeLayout。
最后再思考一下文章开头那个矛盾的问题,为什么Google给开发者默认新建了个RelativeLayout,而自己却在DecorView中用了个LinearLayout。因为DecorView的层级深度是已知而且固定的,上面一个标题栏,下面一个内容栏。采用RelativeLayout并不会降低层级深度,所以此时在根节点上用LinearLayout是效率最高的。而之所以给开发者默认新建了个RelativeLayout是希望开发者能采用尽量少的View层级来表达布局以实现性能最优,因为复杂的View嵌套对性能的影响会更大一些。

参考:
作者:尹star
链接:http://www.jianshu.com/p/8a7d059da746

作者:周君宜
链接:http://www.jianshu.com/p/08e6dab7886e

Relativelayout和LinearLayout对比分析的更多相关文章

  1. Android中RelativeLayout和LinearLayout性能分析

    先看一些现象吧:用eclipse或者Android studio,新建一个Activity自动生成的布局文件都是RelativeLayout,或许你会认为这是IDE的默认设置问题,其实不然,这是由 a ...

  2. 如何优化你的布局层级结构之RelativeLayout和LinearLayout及FrameLayout性能分析

    转载请注明出处:http://blog.csdn.net/hejjunlin/article/details/51159419 如何优化你的布局层级结构之RelativeLayout和LinearLa ...

  3. Android开发——LinearLayout和RelativeLayout的性能对比

    0. 前言 我们都知道新建一个Android项目自动生成的Xml布局文件的根节点默认是RelativeLayout,这不是IDE默认设置,而是由android-sdk\tools\templates\ ...

  4. Android -------- RelativeLayout 和 LinearLayout 的性能分析

    布局的绘制角度 RelativeLayout不如LinearLayout快的根本原因是: RelativeLayout需要对其子View进行两次measure过程, 而LinearLayout则只需一 ...

  5. 浅谈C++之冒泡排序、希尔排序、快速排序、插入排序、堆排序、基数排序性能对比分析之后续补充说明(有图有真相)

    如果你觉得我的有些话有点唐突,你不理解可以想看看前一篇<C++之冒泡排序.希尔排序.快速排序.插入排序.堆排序.基数排序性能对比分析>. 这几天闲着没事就写了一篇<C++之冒泡排序. ...

  6. wait、notify、sleep、interrupt对比分析

    对比分析Java中的各个线程相关的wait().notify().sleep().interrupt()方法 方法简述 Thread类 sleep:暂停当前正在执行的线程:(类方法) yield:暂停 ...

  7. Android和Linux应用综合对比分析

    原文地址:http://www.cnblogs.com/beer/p/3325242.html 免责声明: 当时写完这篇调查报告,给同事看了后,他觉得蛮喜欢,然后想把这篇文章修改一下,然后往期刊上发表 ...

  8. GitHub & Bitbucket & GitLab & Coding 的对比分析

    目前基于 Git 做版本控制的代码托管平台有很多种,比较流行的服务有 Github.Bitbucket. GitLab. Coding,他们各自有什么特点,个人使用者和开发团队又该如何选择? 在这篇文 ...

  9. ArrayList和LinkedList的几种循环遍历方式及性能对比分析(转)

    主要介绍ArrayList和LinkedList这两种list的五种循环遍历方式,各种方式的性能测试对比,根据ArrayList和LinkedList的源码实现分析性能结果,总结结论. 通过本文你可以 ...

随机推荐

  1. WebApi系列(从.Net FrameWork 到 .Net Core)

    一. 简介  1. 什么是WebApi? WebApi是一个很广泛的概念,在这里我们特指.Net平台下的Asp.Net WebApi框架,它是针对各种客户端(浏览器.APP等)来构建Http服务的一个 ...

  2. LOJ #6539 奇妙数论题

    不想咕太久..就随便找个题更一下 LOJ#6539 题意 求题面里那个式子 题解 有一个常用的小式子 $$\sum_{x|a,x|b}\varphi(x)=\gcd(a,b)$$ 用这个式子直接对题面 ...

  3. LOJ #2978「THUSCH 2017」杜老师

    听说LOJ传了THUSC题赶紧上去看一波 随便点了一题都不会做想了好久才会写暴力爆了一发过了... LOJ #2978 题意 $ T$次询问,每次询问$ L,R$,问有多少种选取区间中数的方案使得选出 ...

  4. Mysql5.7数据导出提示--secure-file-priv选项问题的解决方法

    mysql可使用into outfile参数把表中的数据到处到csv,示例如下: select user_id from weibo_comment into outfile '/home/dazha ...

  5. word20170103除了busy,忙的10种英语说法!

    年前,忙死啦!除了busy,这些说法更地道.更形象! #1 I'm swamped! Swamp: 沼泽“忙死了”最形象.最对应的英语说法:It's the end of the year. I'm ...

  6. 419 JQuery and BootStrap

    把葵花宝典剩下的知识讲完了 又学习了bootstrap <link rel="stylesheet" href="css/bootstrap.css"&g ...

  7. GraphQL Java Demo代码

    mvn 引用GraphQL <dependency> <groupId>com.graphql-java</groupId> <artifactId>g ...

  8. 分布式系列十二: Redis高级主题

    持久化 Redis 支持持久化, 其持久化数据有两种方式. 两种可以同时使用. 如果同时使用, Reids 在重启时将使用 AOF 方式来还原数据. RDB 按照一定策略定时同步内存的数据到磁盘.文件 ...

  9. Qt for Android开发总结

    近段时间,本人使用Qt5.3.0开发了Android应用,由于官方资料较少,在此记录开发过程遇到的问题及解决方法 1.Android平台的视频播放,只能使用qml的MediaPlayer 2.qml中 ...

  10. mybatis一对多查询之collection的用法

    首先看一下返回的数据的格式: //获取端子信息List<Map<String, Object>> portList = doneTaskDao.queryTroubleTask ...