Android渲染画面,Android界面渲染优化-程序员宅基地

技术标签: Android渲染画面  

上篇介绍了android界面渲染主要是Display的过程,只要在一个时间段也就是16ms中,CPU和GPU不能正常处理完数据就会产生卡顿.

CPU(中央处理器) :多缓存多分支,适用于复杂的逻辑运算,主要负责Measure,Layout,Record,Execute的计算操作

GPU(图像处理器):众核少缓存,适用于结构单一的数据处理,主要负责Rasterization(栅格化)操作

实际上最后还是回到Measure,Layout,和draw上.也就是说上述三个步骤中的某一个步骤出现了耗时较长的操作,就容易导致界面卡顿。一般来说多发生在draw上。

过度绘制(Overdraw)

什么是过度绘制?

Overdraw(过度绘制)描述的是屏幕上的某个像素在同一帧的时间内被绘制了多次。在多层次重叠的UI结构里面,如果不可见的UI也在做绘制的操作,会导致某些像素区域被绘制了多次。这样就会浪费大量的CPU以及GPU资源。

81c9f7cfe733

image

如何检测过度绘制

开发者选项->调试GPU过度绘制->显示过度绘制区域�

81c9f7cfe733

image

蓝色,淡绿,淡红,深红代表了4种不同程度的Overdraw情况,我们的目标就是尽量减少红色Overdraw,看到更多的蓝色区域

如何优化过度绘制

移除布局中多余的背景

layout层级扁平化,或者该用约束布局(ConstraintLayout)

减少透明度的使用

移除Window默认的Background

通常,我们使用的theme都会包含了一个windowBackground,比如theme的如下:

@color/background_material_light

然后通常我们自己的layout下,会另外加一层背景,这就会引起过度绘制,

android:layout_width="match_parent"

android:layout_height="match_parent"

android:background="@color/white"

android:orientation="vertical">

一般的解决方式把theme下的Background移除

@null

或者在Activity中的onCreate()下添加

getWindow().setBackgroundDrawable(null);

去除子控件的背景

在开发中,经常为了一些视觉效果,需要给子控件附加背景.

android:layout_width="match_parent"

android:layout_height="match_parent"

android:background="@color/white"

android:orientation="vertical">

...

android:background="@drawable/alert_edit_bg1"

... />

如果按照过度绘制的思想来看这个问题的话,那这里也会村子啊过度绘制的情况,最合理的设想是如果子view有背景,并且跟父view背景不同,那么应该移除父view的背景,保留子view的背景,这样就能避免过度绘制了。

不过如果真的严格按照这个逻辑来写代码的话,会导致多写很多代码.况且以目前手机的性能来讲,x1级别的过度绘制不太会影响到性能。

将layout层级扁平化

使用Layout Inspector去查看layout的层次结构

老版本Android SDK提供的是一个Hierarchy Viewer工具,可以用来分析布局深度,

但是在Android studio3.1之后,换成了Layout Inspector,入口在Tools-->Layout Inspector

使用嵌套少的布局

相同层级下,Fragment的效率最高,其次是LinearLayout

LinearLayout对比RelativeLayout

LinearLayout在没有设置weight属性的时候,只会对子视图进行一次measure,而RelativeLayout会在水平方向和竖直方向分别进行一次measure

另外,系统的View的measure方法里对绘制过程做了一个优化,如果我们或者我们的子View没有要求强制刷新,而父View给子View的传入值也没有变化(也就是说子View的位置没变化),就不会做无谓的measure。但是RelativeLayout会做两次measure,而在做横向的测量时,纵向的测量结果尚未完成,只好暂时使用myHeight传入子View系统,假如子View的Height不等于(设置了margin)myHeight的高度,那么measure中上面代码所做得优化将不起作用,所以尽量使用padding代替margin

使用抽象布局 include、merge 、ViewStub

include、merge 、ViewStub这三个布局都是官方提供的用于布局优化的

布局重用 include

标签复用,比起性能上的优化,更大的作用我感觉在xml文件的优化上

减少布局层级 merge

多用于替换FrameLayout或者当一个布局包含另一个时,标签消除视图层次结构中多余的视图组。

如果xml的根部局是FrameLayout,直接替换成merge就能减少一个布局深度。

如果你的主布局文件是垂直布局,引入了一个垂直布局的include,这个时候就可以将include的根布局替换成merge

延迟加载 ViewStub

ViewStub是一个不可见的,大小为0的View,能为xml加载减小不少压力。常用于 进度条、显示错误消息等不需要第一时间显示的视图,inflate()之后会被对应的layout所代替

注:ViewStub目前有个缺陷就是还不支持 标签。

使用lint来优化布局的层次结构

Analyze->Inspect code

布局性能方面的信息位于Android> Lint> Performance下,我们可以点开它来看下一些优化建议。

下面是lint的一些优化技巧:

使用复合图片

如果一个线性布局中包含一个 ImageView 和一个 TextView,可以使用复合图片来替换掉

合并根节点

如果一个FrameLayout 是整个布局的根节点,并且也没有提供背景、留白等等,那么可以使用标签来替换掉,因为DecorView本身就是一个FrameLayout。

移除布局中无用的叶子

布局是一个树形的结构,如果一个布局没有子 View 或者背景,那么可以把它移除掉(这布局本身就不可见了)。

移除无用的父布局

如果一个布局没有兄弟,也不是ScrollView 或者根 View,并且也没有背景,那么可以把这个父布局移除掉,然后把它的子view移到它的父布局下。

避免过深的层次结构

过多的布局嵌套不利于性能,可以使用更扁平化的布局,如RelativeLayout、GridLayout、ConstraintLayout等布局来提高性能。布局默认的最大深度为10

减少透明度的使用

对于不透明的view,只需要渲染一次即可把它显示出来。但是如果这个view设置了alpha值,则至少需要渲染两次。这是因为使用了alpha的view需要先知道混合view的下一层元素是什么,然后再结合上层的view进行Blend混色处理。透明动画、淡入淡出和阴影等效果都涉及到某种透明度,这就会造成了过度绘制。可以通过减少渲染这些透明对象来改善过度绘制。比如:在TextView上设置带透明度alpha值的黑色文本可以实现灰色的效果。但是,直接通过设置灰色的话能够获得更好的性能。

减少自定义View的过度绘制,使用clipRect()和QuickReject()

clipRect():可以指定一块矩形区域,只有在这个区域内才会被绘制,其他的区域会被忽视,可以有效的节约CPU与GPU的资源

canvas.clipRect(0, 0,200,200); //指定(0,0)到(200,200)的矩形区域为绘制区域

QuickReject():判断画布是否与你指定的矩形相交,借此来决定是否需要绘制该画布

boolean skipDraw=canvas.quickReject(new RectF(), Canvas.EdgeType.AA);

onDraw()中不要创建新的局部变量以及不要做耗时操作

onDraw()中不要创建新的局部变量,因为onDraw()方法可能会被频繁调用,大量的临时对象会导致内存抖动,会造成频繁的GC,从而使UI线程被频繁阻塞,导致画面卡顿。这种问题一般android studio的lint静态检查都会报警告,平时多注意些android studio标黄的警告,有助于性能调优

尝试使用ConstraintLayout

较高的性能优势

比起LinearLayout 、RelativeLayout等,ConstraintLayout可以用更少的布局层级来达到相同的效果

完美的屏幕适配

ConstraintLayout的大小、距离都可以使用比例来设置,所以其适配性更好。

当然不是任何时候都推荐使用ConstraintLayout的,在简单的布局下还是建议使用LinearLayout 、RelativeLayout,因为对于相同层级的布局下,ConstraintLayout的measure,layout,draw等过程会显得更加重.

参考文档

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/weixin_34469152/article/details/117346424

智能推荐

从零开始搭建Hadoop_创建一个hadoop项目-程序员宅基地

文章浏览阅读331次。第一部分:准备工作1 安装虚拟机2 安装centos73 安装JDK以上三步是准备工作,至此已经完成一台已安装JDK的主机第二部分:准备3台虚拟机以下所有工作最好都在root权限下操作1 克隆上面已经有一台虚拟机了,现在对master进行克隆,克隆出另外2台子机;1.1 进行克隆21.2 下一步1.3 下一步1.4 下一步1.5 根据子机需要,命名和安装路径1.6 ..._创建一个hadoop项目

心脏滴血漏洞HeartBleed CVE-2014-0160深入代码层面的分析_heartbleed代码分析-程序员宅基地

文章浏览阅读1.7k次。心脏滴血漏洞HeartBleed CVE-2014-0160 是由heartbeat功能引入的,本文从深入码层面的分析该漏洞产生的原因_heartbleed代码分析

java读取ofd文档内容_ofd电子文档内容分析工具(分析文档、签章和证书)-程序员宅基地

文章浏览阅读1.4k次。前言ofd是国家文档标准,其对标的文档格式是pdf。ofd文档是容器格式文件,ofd其实就是压缩包。将ofd文件后缀改为.zip,解压后可看到文件包含的内容。ofd文件分析工具下载:点我下载。ofd文件解压后,可以看到如下内容: 对于xml文件,可以用文本工具查看。但是对于印章文件(Seal.esl)、签名文件(SignedValue.dat)就无法查看其内容了。本人开发一款ofd内容查看器,..._signedvalue.dat

基于FPGA的数据采集系统(一)_基于fpga的信息采集-程序员宅基地

文章浏览阅读1.8w次,点赞29次,收藏313次。整体系统设计本设计主要是对ADC和DAC的使用,主要实现功能流程为:首先通过串口向FPGA发送控制信号,控制DAC芯片tlv5618进行DA装换,转换的数据存在ROM中,转换开始时读取ROM中数据进行读取转换。其次用按键控制adc128s052进行模数转换100次,模数转换数据存储到FIFO中,再从FIFO中读取数据通过串口输出显示在pc上。其整体系统框图如下:图1:FPGA数据采集系统框图从图中可以看出,该系统主要包括9个模块:串口接收模块、按键消抖模块、按键控制模块、ROM模块、D.._基于fpga的信息采集

微服务 spring cloud zuul com.netflix.zuul.exception.ZuulException GENERAL-程序员宅基地

文章浏览阅读2.5w次。1.背景错误信息:-- [http-nio-9904-exec-5] o.s.c.n.z.filters.post.SendErrorFilter : Error during filteringcom.netflix.zuul.exception.ZuulException: Forwarding error at org.springframework.cloud..._com.netflix.zuul.exception.zuulexception

邻接矩阵-建立图-程序员宅基地

文章浏览阅读358次。1.介绍图的相关概念  图是由顶点的有穷非空集和一个描述顶点之间关系-边(或者弧)的集合组成。通常,图中的数据元素被称为顶点,顶点间的关系用边表示,图通常用字母G表示,图的顶点通常用字母V表示,所以图可以定义为:  G=(V,E)其中,V(G)是图中顶点的有穷非空集合,E(G)是V(G)中顶点的边的有穷集合1.1 无向图:图中任意两个顶点构成的边是没有方向的1.2 有向图:图中..._给定一个邻接矩阵未必能够造出一个图

随便推点

MDT2012部署系列之11 WDS安装与配置-程序员宅基地

文章浏览阅读321次。(十二)、WDS服务器安装通过前面的测试我们会发现,每次安装的时候需要加域光盘映像,这是一个比较麻烦的事情,试想一个上万个的公司,你天天带着一个光盘与光驱去给别人装系统,这将是一个多么痛苦的事情啊,有什么方法可以解决这个问题了?答案是肯定的,下面我们就来简单说一下。WDS服务器,它是Windows自带的一个免费的基于系统本身角色的一个功能,它主要提供一种简单、安全的通过网络快速、远程将Window..._doc server2012上通过wds+mdt无人值守部署win11系统.doc

python--xlrd/xlwt/xlutils_xlutils模块可以读xlsx吗-程序员宅基地

文章浏览阅读219次。python–xlrd/xlwt/xlutilsxlrd只能读取,不能改,支持 xlsx和xls 格式xlwt只能改,不能读xlwt只能保存为.xls格式xlutils能将xlrd.Book转为xlwt.Workbook,从而得以在现有xls的基础上修改数据,并创建一个新的xls,实现修改xlrd打开文件import xlrdexcel=xlrd.open_workbook('E:/test.xlsx') 返回值为xlrd.book.Book对象,不能修改获取sheett_xlutils模块可以读xlsx吗

关于新版本selenium定位元素报错:‘WebDriver‘ object has no attribute ‘find_element_by_id‘等问题_unresolved attribute reference 'find_element_by_id-程序员宅基地

文章浏览阅读8.2w次,点赞267次,收藏656次。运行Selenium出现'WebDriver' object has no attribute 'find_element_by_id'或AttributeError: 'WebDriver' object has no attribute 'find_element_by_xpath'等定位元素代码错误,是因为selenium更新到了新的版本,以前的一些语法经过改动。..............._unresolved attribute reference 'find_element_by_id' for class 'webdriver

DOM对象转换成jQuery对象转换与子页面获取父页面DOM对象-程序员宅基地

文章浏览阅读198次。一:模态窗口//父页面JSwindow.showModalDialog(ifrmehref, window, 'dialogWidth:550px;dialogHeight:150px;help:no;resizable:no;status:no');//子页面获取父页面DOM对象//window.showModalDialog的DOM对象var v=parentWin..._jquery获取父window下的dom对象

什么是算法?-程序员宅基地

文章浏览阅读1.7w次,点赞15次,收藏129次。算法(algorithm)是解决一系列问题的清晰指令,也就是,能对一定规范的输入,在有限的时间内获得所要求的输出。 简单来说,算法就是解决一个问题的具体方法和步骤。算法是程序的灵 魂。二、算法的特征1.可行性 算法中执行的任何计算步骤都可以分解为基本可执行的操作步,即每个计算步都可以在有限时间里完成(也称之为有效性) 算法的每一步都要有确切的意义,不能有二义性。例如“增加x的值”,并没有说增加多少,计算机就无法执行明确的运算。 _算法

【网络安全】网络安全的标准和规范_网络安全标准规范-程序员宅基地

文章浏览阅读1.5k次,点赞18次,收藏26次。网络安全的标准和规范是网络安全领域的重要组成部分。它们为网络安全提供了技术依据,规定了网络安全的技术要求和操作方式,帮助我们构建安全的网络环境。下面,我们将详细介绍一些主要的网络安全标准和规范,以及它们在实际操作中的应用。_网络安全标准规范