Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >Android性能优化(二)之布局优化面面观

Android性能优化(二)之布局优化面面观

作者头像
用户2898788
发布于 2018-08-21 02:07:37
发布于 2018-08-21 02:07:37
1.1K00
代码可运行
举报
文章被收录于专栏:双十二技术哥双十二技术哥
运行总次数:0
代码可运行

一、初识布局优化

通过《Android性能优化(一)之启动加速35%》我们获得了闪电般的App启动速度,那么在应用启动完毕之后,UI布局也会对App的性能产生比较大的影响,如果布局写得糟糕,显而易见App的表现不可能流畅。

那么本文我同样基于实际案例,针对应用的布局进行优化进而提升App性能。

二、60fps VS 16ms

根据Google官方出品的Android性能优化典范,60帧每秒是目前最合适的图像显示速度,事实上绝大多数的Android设备也是按照每秒60帧来刷新的。为了让屏幕的刷新帧率达到60fps,我们需要确保在时间16ms(1000/60Hz)内完成单次刷新的操作(包括measure、layout以及draw),这也是Android系统每隔16ms就会发出一次VSYNC信号触发对UI进行渲染的原因。

如果整个过程在16ms内顺利完成则可以展示出流畅的画面;然而由于任何原因导致接收到VSYNC信号的时候无法完成本次刷新操作,就会产生掉帧的现象,刷新帧率自然也就跟着下降(假定刷新帧率由正常的60fps降到30fps,用户就会明显感知到卡顿)。

作为开发人员,我们的目标只有一个:保证稳定的帧率来避免卡顿。

三、Avoid Overdraw

理论上一个像素每次只绘制一次是最优的,但是由于重叠的布局导致一些像素会被多次绘制,Overdraw由此产生。

我们可以通过调试工具来检测Overdraw:设置——开发者选项——调试GPU过度绘制——显示过度绘制区域。

原色 – 没有过度绘制 – 这部分的像素点只在屏幕上绘制了一次。 蓝色 – 1次过度绘制– 这部分的像素点只在屏幕上绘制了两次。 绿色 – 2次过度绘制 – 这部分的像素点只在屏幕上绘制了三次。 粉色 – 3次过度绘制 – 这部分的像素点只在屏幕上绘制了四次。 红色 – 4次过度绘制 – 这部分的像素点只在屏幕上绘制了五次。

在实际项目中,一般认为蓝色即是可以接受的颜色。

我们来看一个简单却隐藏了很多问题的界面,App的设置界面。在没有优化之前打开Overdraw调试,可以看到界面大多数是严重的红色:见下图。

贴出这个布局的代码(贴出后超过公众号字数限制,可以点击查看原文查看布局代码)。

每一行布局都使用RelativeLayout嵌套来做,而且设置了多重颜色。

分析布局可知:多层布局重复设置了背景色导致Overdraw。 那么我们结合产品的需求(任何不结合具体场景优化都是耍流氓):

  • 去掉每行RelativeLayout的背景色;
  • 去掉每行TextView的背景色;

备注:一个容易忽略的点是我们的Activity使用的Theme可能会默认的加上背景色,不需要的情况下可以去掉。

去掉背景色之后再看一下Overdraw;

对比一下优化后的布局的颜色,可以看出Overdraw降到了可以接受的程度。

备注:有些过度绘制都是不可避免的,需要结合具体的布局场景具体分析。

四、减少嵌套层次及控件个数

  • Android的布局文件的加载是LayoutInflater利用pull解析方式来解析,然后根据节点名通过反射的方式创建出View对象实例;
  • 同时嵌套子View的位置受父View的影响,类如RelativeLayout、LinearLayout等经常需要measure两次才能完成,而嵌套、相互嵌套、深层嵌套等的发生会使measure次数呈指数级增长,所费时间呈线性增长;

由此得到结论:那么随着控件数量越多、布局嵌套层次越深,展开布局花费的时间几乎是线性增长,性能也就越差。

幸运的是,我们有Hierarchy Viewer这个方便可视化的工具,可以得到:树形结构总览、布局view、每一个View(包含子View)绘制所花费的时间及View总个数

备注: Hierarchy Viewer不能连接真机的问题可以通过ViewServer这个库解决;

使用Hierarchy Viewer来看查看一下设置界面,可以从下图中得到设置界面的一些数据及存在的问题:

  • 嵌套共计7层(仅setContentView设置的布局),布局嵌套过深;
  • measure时间1.569ms,layout时间0.120ms,draw时间16.128ms,合计共计耗时17.871ms;
  • 共绘制85个View,5个多余定位,以及若干个无用布局。

优化方案:

  • 将之前使用RelativeLayout来做的可以替换的行换为TextView;
  • 去掉之前多余的无用布局;

现在我们再使用Hierarchy Viewer来检测一下:

优化后: 1. 控件数量从85个减少到26个,减少69%; 2. 绘制时间从17.8ms减少到14.756ms,降低17%;

总结: 1. 同样的UI效果可以使用不同的布局来完成,我们需要考虑使用少的嵌套层次以及控件个数来完成,例如设置界面的普通一行,可以像之前一样使用RelativeLayout嵌套TextView以及ImageView来实现,但是明显只使用TextView来做:嵌套层次、控件个数都更少。 2. 优化过程中使用低端手机更易发现瓶颈;

五、Profiling GPU Rendering

根据Android性能优化典范,打开设备的GPU配置渲染工具——》在屏幕上显示为条形图,可以协助我们定位UI渲染问题。

从Android M版本开始,GPU Profiling工具把渲染操作拆解成如下8个详细的步骤进行显示。

  1. Swap Buffers:表示处理任务的时间,也可以说是CPU等待GPU完成任务的时间,线条越高,表示GPU做的事情越多;
  2. Command Issue:表示执行任务的时间,这部分主要是Android进行2D渲染显示列表的时间,为了将内容绘制到屏幕上,Android需要使用Open GL ES的API接口来绘制显示列表,红色线条越高表示需要绘制的视图更多;
  3. Sync & Upload:表示的是准备当前界面上有待绘制的图片所耗费的时间,为了减少该段区域的执行时间,我们可以减少屏幕上的图片数量或者是缩小图片的大小;
  4. Draw:表示测量和绘制视图列表所需要的时间,蓝色线条越高表示每一帧需要更新很多视图,或者View的onDraw方法中做了耗时操作;
  5. Measure/Layout:表示布局的onMeasure与onLayout所花费的时间,一旦时间过长,就需要仔细检查自己的布局是不是存在严重的性能问题;
  6. Animation:表示计算执行动画所需要花费的时间,包含的动画有ObjectAnimator,ViewPropertyAnimator,Transition等等。一旦这里的执行时间过长,就需要检查是不是使用了非官方的动画工具或者是检查动画执行的过程中是不是触发了读写操作等等;
  7. Input Handling:表示系统处理输入事件所耗费的时间,粗略等于对事件处理方法所执行的时间。一旦执行时间过长,意味着在处理用户的输入事件的地方执行了复杂的操作;
  8. Misc Time/Vsync Delay:表示在主线程执行了太多的任务,导致UI渲染跟不上vSync的信号而出现掉帧的情况;出现该线条的时候,可以在Log中看到这样的日志:

备注:GPU配置渲染工具虽然可以定位出问题发生在某个步骤,但是并不能定位到具体的某一行;当我们定位到某个步骤之后可以使用工具TraceView进行更加详细的定位。TraceView的使用可以参照《Android性能优化(一)之启动加速35%》

六、Use Tags

merge标签

merge可以用来合并布局,减少布局的层级。merge多用于替换顶层FrameLayout或者include布局时,用于消除因为引用布局导致的多余嵌套。 例如:需要显示一个Button,布局如下;

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Merge标签演示" />
</LinearLayout>

我们通过UiAutoMatorViewer(无需root,相比Hierarchy Viewer只能查看布局层次,不能得到绘制时间)看一下布局的层次

我们使用Merge标签对代码进行修改;

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Merge标签演示" />
</merge>

再看下布局的层次:

可以看到使用Merge标签进行优化之后布局嵌套就少了一层,Button作为父视图第三层FrameLayout的直接子视图。

注意:merge标签常用于减少布局嵌套层次,但是只能用于根布局。

ViewStub标签

推迟创建对象、延迟初始化,不仅可以提高性能,也可以节省内存(初始化对象不被创建)。Android定义了ViewStub类,ViewStub是轻量级且不可见的视图,它没有大小,没有绘制功能,也不参与measure和layout,资源消耗非常低。 1、

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
    <ViewStub
        android:id="@+id/mask"
        android:layout="@layout/b_me_mask"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
ViewStub viewStub = (ViewStub)view.findViewById(R.id.mask);
viewStub.inflate();

App里常见的视图如蒙层、小红点,以及网络错误、没有数据等公共视图,使用频率并不高,如果每一次都参与绘制其实是浪费资源的,都可以借助ViewStub标签进行延迟初始化,仅当使用时才去初始化。

include标签

include标签和布局性能关系不大,主要用于布局重用,一般和merge标签配合使用,因和本文主题关联不大,此处不展开讨论。

七、其它

  1. 自定义控件时,注意在onDraw不能进行复杂运算;以及对待三方UI库选择高性能;
  2. 内存对布局的影响:如同Misc Time/Vsync Delay步骤产生的影响,在之后内存优化的篇章详细讲。

八、总结

布局优化的通用套路
  1. 调试GPU过度绘制,将Overdraw降低到合理范围内;
  2. 减少嵌套层次及控件个数,保持view的树形结构尽量扁平(使用Hierarchy Viewer可以方便的查看),同时移除所有不需要渲染的view;
  3. 使用GPU配置渲染工具,定位出问题发生在具体哪个步骤,使用TraceView精准定位代码;
  4. 使用标签,Merge减少嵌套层次、ViewStub延迟初始化。

经过这几步的优化之后,一般就不会再有布局的性能问题,同时还是要强调:优化是一个长期的工作,同时也必须结合具体场景:有取有舍!

参考:Android性能优化典范

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2017-02-17,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 双十二技术哥 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
Google软件测试之道(读书笔记)
Google软件测试之道(读书笔记) 目录 第一章 Google软件测试介绍 第二章 软件测试开发工程师 第三章 测试工程师 第四章 测试工程经理 第五章 Google软件测试改进 第一章 Google软件测试介绍 角色、类型、行为、组织结构: 划分测试: 版本类型、迭代开发: 本章总览: 第二章 软件测试开发工程师 SET的工作: 自动化计划: 测试运行要求: 测试认证: SET的招聘: 本章总览: 第三章 测试工程师 维护模式的测试:
wangmcn
2022/07/26
3160
Google软件测试之道(读书笔记)
《人人都是产品经理》--读书笔记
从一名开发转岗为运营,希望一步一步脚踏实地的夯实基础,不要眼高手低,怀有空杯精神,借助读书笔记,沉淀一些想法。
Techeek
2018/03/21
2.5K4
《人人都是产品经理》--读书笔记
《学习之道》读书笔记
    本书也是一本讲学习方法的书籍,这本书不是讲有什么学习的灵丹妙药,而是从理论以及科学来告诉你为什么学习是一件痛苦并且艰难的事情,以及从科学的角度如何避过难关,这本书记述的核心思想是「搭建思维组块」,其实就是一种思维框架的搭建,最后,】如果你想最快速的从这本书学到点什么,最好的方式是从 「228」 页的十条好建议和坏建议入手,带入到你的生活中进行实践。
阿东
2021/10/20
5750
架构整洁之道读书笔记(一)
《架构整洁之道》是创造“Clean神话”的Bob大叔在架构领域的登峰之作。本篇是架构整洁之道读书笔记的开篇。
coderidea
2022/06/08
3460
组织行为学读书笔记
管理者(managers)通过别人来完成工作。他们做出决策,分配资源,指导别人的活动从而实现工作目标。 管理者在组织(organization)当中完成他们的工作。
lilugirl
2019/05/26
8640
读书笔记|DAMA-第一章 数据管理
DAMA认证的教材,没报考也没报班,但是买了书。一些知识“知道”和成体系往往是两码事,证不证的不重要,含金量如何也不重要,重要的是读书本身就是有收获的。
做数据的二号姬
2023/09/06
2170
读书笔记|DAMA-第一章 数据管理
深入理解计算机系统读书笔记之第二章信息的表示和处理
这一章读完,嗯,感觉怎么说呢? 就是读完了而已,没有想第一章那样,有具体的一些收获什么的。可能是没有很认真的阅读。读的很匆忙,有的内容很晦涩难懂............ 不管怎样还是在写一写自己的收获吧 这一章讲的是信息的表示和处理, 信息在系统中是怎样表示的呢?就是以字节来进行存储。信息就是位+上下文(第一章里面讲的) 具体的信息是怎样表示的? 带符号整数,不带符号整数,浮点数,等等。 1位运算 移位,向右移位 x>>k 分为两种形式 (1)逻辑上,向右移位就是在左端添加k个零[an-1,an-2,...
用户1631856
2018/04/12
1K0
你真的懂什么叫数据挖掘吗?
我对做事的流程非常感兴趣。我想要知道一些可以把事情做好的好方法,甚至在可能的情况下可以知道做这些事情的最好方式。就算你的技能不强,理解相关方面的知识不深,这个过程也可以帮你在后面长时间的过程中解决这些问题。它可以指引你如何变得更有技能,同时对相关知识有深层次的了解。至少,我曾经就是用这样的方式完成了很多的工作。 我认为学习数据挖掘是很有用的,正如它以从数据中进行发现的过程的形式展现出来的那样。在这篇文章中,你会从相关的教材和论文中探索一些关于“数据挖掘”的官方定义。就像数据挖掘是一个过程那样,数据挖掘的定义
CDA数据分析师
2018/02/11
1.3K0
你真的懂什么叫数据挖掘吗?
读书笔记|DAMA认证知识体系思维导图合集
按照我的习惯,内容大纲的思维导图不会有全部的内容,只会有我觉得有价值的内容。这个是读书笔记,而不是考试框架,有一定概率漏掉了考试考点,毕竟我觉得有价值不代表是考点,考点的内容我不一定觉得对我有价值。
做数据的二号姬
2023/11/03
5601
读书笔记|DAMA认证知识体系思维导图合集
【译】你真的知道数据挖掘的秘密吗?
版权申明 作者:Jason Brownlee 原文链接:http://machinelearningmastery.com/what-is-data-mining-and-kdd/ 翻译:品言 审核:陆勤 PPV课原创翻译文章,如需转载请微信留言获得授权,不得未经授权转载! 我对做事的流程非常感兴趣。我想要知道一些可以把事情做好的好方法,甚至在可能的情况下可以知道做这些事情的最好方式。就算你的技能不强,理解相关方面的知识不深,这个过程也可以帮你在后面长时间的过程
小莹莹
2018/04/23
6430
【译】你真的知道数据挖掘的秘密吗?
【读书笔记】《漫画算法》:克服对算法的恐惧,从漫画开始
在上小学和初高中的时候,要我写读后感这种东西,我是非常厌恶的。无非就是老师布置的一个作业,还是那种无趣且磨人的工作。
蛮三刀酱
2020/06/20
4530
终、《图解HTTP》读书笔记 - 汇总篇(总结)
又一本网络基础的书啃完了,这本书建议结合[《网络是怎么样连接的》读书笔记 - 汇总篇]这一篇读书笔记食用(当然也可以直接看原书)。
阿东
2022/08/13
1.3K0
终、《图解HTTP》读书笔记 - 汇总篇(总结)
手把手教你设计CPU(蜂鸟书)读书笔记
这本书讲的是如何用verilog,以riscv为指令集,设计一款CPU。也就是书中说的蜂鸟E200。之前没有看过类似的书,对CPU的工作流程也不熟悉。这本书以verilog为载体,介绍了CPU的基本原理,对于第一次接触CPU内部眼里的菜鸟来说,简直不要太神奇。而且本书开源代码,只要有一块fpga,你也能够自己做出一块CPU来。
用户1148523
2020/06/11
1.7K0
手把手教你设计CPU(蜂鸟书)读书笔记
高性能Mysql第一章读书笔记
第一章 mysql架构和历史 mysql最重要最与众不同的是它的存储引擎架构,这种架构设计将查询处理,以及其他系统任务和数据的存储和提取相分离。 存储引擎负责MySQL中数据的储存和提取。 每个客户端连接都会在服务器进程中拥有一个线程,这个连接的查询只会在这个单独的线程中进行。 对于select语句,在解析查询之前,服务器会先检查查询缓存。 一种提高共享对象并发性的方式就是让锁定对象更有选择性,但是增加锁的数量也会增加系统开销,需要在锁的开销和安全性之间寻求平衡。 mysql有两种锁策略,表锁和行锁。 AC
用户7962184
2020/11/20
3390
《硅谷钢铁侠》---- 读书笔记
真正好的作品必须在两方面非常突出。 其一,提供许多过去没有人说过的精彩故事; 其二,不以偏概全,为一位重要人物的曲折人生提供完整说明。
流川疯
2022/05/10
8740
《硅谷钢铁侠》---- 读书笔记
N、《图解HTTP》读书笔记 - 附录
附录部分是把之前各个章节参考的各种文章和资料汇总一遍,如果你也想阅读这本书,相信这些内容对你一定有帮助。
阿东
2022/08/12
4160
N、《图解HTTP》读书笔记 - 附录
【学习】《R实战》读书笔记(第一章)
第一章 R简介 本章概要 1安装R 2理解R语言 3运行R程序 本章所介绍的内容概括如下。 一个典型的数据分析步骤如图1所示。 图1:典型数据分析步骤 简而言之,现今的数据分析要求我们从多种数据源中获取数据、数据合并、标注、清洗和分析,并且把分析的结果进行展示,形成报告或者系统,辅助决策。R能够满足现今数据分析的要求。 为什么用R? R是一个适合统计分析和绘图的环境与语言。它是开源、免费的,获得世界范围社区支持。统计分析和绘图工具已经很多了,例如:SPSS,SAS,Excel,Stata和Minit
小莹莹
2018/04/19
8100
【学习】《R实战》读书笔记(第一章)
《深入架构原理与实践》| 读书笔记
引言 随着云计算的兴起,技术架构的关注点也从集群可用性治理,发展到云原生和 FinOps 成本管理。 该书涵盖了网络、容器、网关、微服务与分布式、云原生、质量监测和成本管理方面的内容,帮助读者快速理清云时代下的技术架构体系。 本笔记大多为个人理解后的知识点, 仅供参考 第一章:云原生技术概论 CNCF(Cloud Native Computing Foundation,云原生计算基金会) Service Mesh(服务网格) Serverless(无服务器架构)
yiyun
2023/09/30
4670
《深入架构原理与实践》| 读书笔记
深入理解PHP读书笔记
第一章 高级PHP技巧 1.1 多维数组排序 1.1.1 多维数组排序 $a=array( array('key1'=>940,'key2'=>'blah'), array('
lilugirl
2019/05/26
4160
《Java 8实战》阅读笔记(1)
给方法listFiles传递方法引用**File::isHidden**
阿杜
2018/08/06
5090
《Java 8实战》阅读笔记(1)
推荐阅读
相关推荐
Google软件测试之道(读书笔记)
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验