布局性能优化:安卓开发者不可错过的性能优化技巧
作者:麦客奥德彪
当我们开发Android应用时,布局性能优化是一个必不可少的过程。一个高效的布局能够提高用户体验,使应用更加流畅、响应更加迅速,而低效的布局则会导致应用的运行变得缓慢,甚至出现卡顿、崩溃等问题,影响用户体验。在开发中,布局优化不仅需要考虑到UI设计的美观性和易用性,还需要关注布局的性能,避免出现因视图过多、嵌套过深、图片过大等问题导致的性能瓶颈。通过对布局进行优化,可以显著提高应用的性能和用户体验,减少应用的CPU和内存占用,加快应用的启动和响应速度,降低应用的耗电量,从而提高应用的稳定性和可靠性。
布局性能优化对于提高Android应用的质量和竞争力是至关重要的。在实际开发中,我们需要根据具体的业务场景和设计要求,结合布局优化的最佳实践,逐步提升应用的布局性能,为用户带来更好的体验。
布局为什么会有性能问题呢
那需要了解一下Android View的渲染机制,Android渲染机制是指Android系统中用于显示界面的工作流程。它包括视图树的构建、测量、布局和绘制四个过程。
他们的大致流程是

- 构建视图树(View Hierarchy):在应用启动时,Android系统会根据布局文件中定义的View、ViewGroup和其他组件创建一个视图树。视图树是根据xml进行解析的。
- 测量(Measure):在测量过程中,系统会遍历视图树,并计算每个视图的大小和位置
- 布局(Layout):在布局过程中,系统会根据视图树中每个视图的测量结果,确定每个视图的大小和位置,并将其放置在正确的位置上
- 绘制(Draw):在绘制过程中,系统会遍历视图树,并将每个视图绘制到屏幕上
在这几个过程中,布局过程是比较耗费时间的,并且耗时与视图树的复杂程度成正比。
复杂的布局指的是树关系的复杂,而不是元素的复杂。
不一样的角度
从系统角度分析,Android系统的UI界面是基于视图层次结构(View Hierarchy)构建的,每个UI元素都是View或ViewGroup对象的实例,这些对象按照它们在界面中出现的顺序排列,构成了一个视图层次结构。在这个结构中,每个UI元素都有自己的父元素和子元素,因此构成了一个树形结构。这个树形结构的根节点是一个ViewGroup对象,它是整个视图层次结构的根。
当用户进行交互操作时,Android系统需要对视图层次结构进行更新,例如重新布局、重绘等操作,这些操作会消耗大量的CPU和内存资源。因此,视图层次结构的构建对应用程序的性能和响应速度至关重要。
常见布局解析,用对了,你的性能问题会减少很多
我们从开始学习Android就知道五大布局是Android的布局基础,大家还记得他们的优缺点吗?之所以有五大布局,就是因为他们使用场景各不相同,然而有时候写法就是上来就相对,别的不考虑,这正确吗?
这是一个对比表格,加颜色的,年龄小的程序员可能都不知道。

通过这个对比,你会发现,每一个布局都有它的用途,要是用对了,在性能方面都有提升。也不是说用约束布局一撸到底,在有些专场的场景中,对应的布局更加优于约束布局。
回顾完之后,我们看看开发中还有哪些影响性能的写法。
常见的开发中有损布局性能的操作方式
嵌套层数过多
当一个布局容器包含多个子布局容器时,会导致视图层次结构的深度增加,从而增加了CPU和内存资源的消耗
<LinearLayout><RelativeLayout></RelativeLayout><LinearLayout></LinearLayout>
</LinearLayout>
内存使用过高
当一个布局容器包含大量的子视图时,会导致内存占用过高,从而影响应用程序的性能
<RelativeLayout><ImageView/><ImageView/><ImageView/></RelativeLayout>
不合适的布局容器
在布局中选择合适的布局容器可以避免不必要的布局操作和内存消耗(当需要显示大量的数据列表时,使用ListView或RecyclerView等容器可以避免不必要的视图更新和内存消耗)
过多的重绘操作
当一个布局容器中包含多个视图时,每次修改其中一个视图的属性,都会导致整个布局容器的重绘操作
可以使用ViewStub元素来延迟加载复杂的视图。
不合理的布局属性
在布局中选择合适的布局属性可以避免不必要的视图更新和内存消耗
在使用RelativeLayout布局容器时,它的测量和布局都需要参考父、兄等原则,所以需要考虑到视图的相对位置和大小,以避免不必要的布局操作和内存消耗。
使用无效的布局容器
在布局中使用无效的布局容器会增加不必要的布局操作和内存消耗,影响应用程序的性能和响应速度
<TableLayout><TableRow><TextView/><TextView/></TableRow><TableRow><TextView/><TextView/></TableRow>
</TableLayout>
这种操作在开发中还是比较常见的,有时候为了给Text View或者ImageView 添加点击区域,外边搞一个FragmeLayout。这种操作会导致内存消耗过高的。
常见的检测布局性能工具
- Hierarchy Viewer工具:Hierarchy Viewer工具可以帮助开发者分析应用程序的视图层次结构,找出可能存在的性能问题。在Hierarchy Viewer中,可以查看应用程序的视图层次结构,以及每个视图的绘制时间、测量时间和布局时间等性能指标。
- TraceView工具:TraceView工具可以帮助开发者分析应用程序的性能问题,包括布局性能问题。在TraceView中,可以查看应用程序的方法调用链和执行时间等信息,以及每个方法的CPU使用率、内存消耗等性能指标。
- UI性能分析器:Android Studio中内置了UI性能分析器,可以帮助开发者分析应用程序的UI性能问题,包括布局性能问题。在UI性能分析器中,可以查看应用程序的渲染时间、FPS、布局时间等性能指标,并根据性能指标分析应用程序的性能问题。
- Monkey测试工具:Monkey测试工具可以帮助开发者测试应用程序的稳定性和性能问题,包括布局性能问题。在Monkey测试中,可以模拟用户随机点击和滑动操作,以测试应用程序的稳定性和响应速度,同时可以通过TraceView等工具分析应用程序的性能问题。(提前做好监测的买点,trace收集,然后用monkey测试,最后分析trace)
总结
1.减少布局层次
布局层次越深,绘制所需的时间就越长,因此应该尽可能减少布局层次。可以通过使用 ConstraintLayout 或者自定义 View 来减少布局层次。
2.使用合适的布局容器
应该选择最适合当前布局需求的布局容器,避免使用过于复杂的布局容器,比如 LinearLayout 嵌套多层、RelativeLayout 的多重嵌套等。
3.使用 ViewStub 来延迟加载视图
如果布局中包含复杂的视图,可以考虑使用 ViewStub 来延迟加载这些视图,以减少布局的加载时间。
4.避免使用过多的嵌套布局
嵌套布局会增加布局的复杂度,导致渲染时间变长。因此应该尽量避免过多的嵌套布局。
5.使用合适的布局属性
合理使用布局属性可以让布局更加简洁、高效,比如使用 match_parent 和 wrap_content 来替代具体的像素值。
6.避免在布局文件中使用过多的 include 标签
include 标签可以重复使用布局,但是过多的使用会增加布局层次和渲染时间,因此应该尽量避免在布局文件中使用过多的 include 标签
主要是要弄明白布局的使用场景,从这几个坑出发,写代码的时候上点心。
为了帮助到大家更好的全面清晰的掌握好性能优化,准备了相关的核心笔记(还该底层逻辑):https://qr18.cn/FVlo89
性能优化核心笔记:https://qr18.cn/FVlo89
启动优化

内存优化

UI优化

网络优化

Bitmap优化与图片压缩优化:https://qr18.cn/FVlo89

多线程并发优化与数据传输效率优化

体积包优化

《Android 性能监控框架》:https://qr18.cn/FVlo89

《Android Framework学习手册》:https://qr18.cn/AQpN4J
- 开机Init 进程
- 开机启动 Zygote 进程
- 开机启动 SystemServer 进程
- Binder 驱动
- AMS 的启动过程
- PMS 的启动过程
- Launcher 的启动过程
- Android 四大组件
- Android 系统服务 - Input 事件的分发过程
- Android 底层渲染 - 屏幕刷新机制源码分析
- Android 源码分析实战

相关文章:
布局性能优化:安卓开发者不可错过的性能优化技巧
作者:麦客奥德彪 当我们开发Android应用时,布局性能优化是一个必不可少的过程。一个高效的布局能够提高用户体验,使应用更加流畅、响应更加迅速,而低效的布局则会导致应用的运行变得缓慢,甚至出现卡顿、崩溃等问题&…...
Python 中的机器学习简介:多项式回归
一、说明 多项式回归可以识别自变量和因变量之间的非线性关系。本文是关于回归、梯度下降和 MSE 系列文章的第三篇。前面的文章介绍了简单线性回归、回归的正态方程和多元线性回归。 二、多项式回归 多项式回归用于最适合曲线拟合的复杂数据。它可以被视为多元线性回归的子集。…...
docker 容器中执行命令出现错误: 13: Permission denied
错误 13: Permission denied [rootVM-32-11-tencentos ~]# docker exec -it kibana1 /bin/bash kibana76c20c215dcb:~$ apt-get install vi E: Could not open lock file /var/lib/dpkg/lock-frontend - open (13: Permission denied) E: Unable to acquire the dpkg frontend…...
JavaWeb学习|JavaBean;MVC三层架构;Filter;Listener
1.JavaBean 实体类 JavaBean有特定的写法: 必须要有一个无参构造 属性必须私有化。 必须有对应的get/set方法 用来和数据库的字段做映射 ORM; ORM:对象关系映射 表--->类 字段-->属性 行记录---->对象 2.<jsp:useBean 标签 3. MVC三层架构 4. Filter …...
arx 外部参照文件(XREF)的添加、删除、卸载和重载_objectarx
添加参照 CString strFileName;int nIndex = strFilePath.ReverseFind(\\);if (nIndex != -1){strFileName = strFilePath.Right(strFilePath....
【博客699】docker daemon预置iptables剖析
docker daemon预置iptables剖析 没有安装docker的机器:iptables为空,且每个链路的默认policy均为ACCEPT [root~]# iptables-save[root ~]# iptables -t raw -nvL Chain PREROUTING (policy ACCEPT 0 packets, 0 bytes)pkts bytes target prot opt …...
Golang 中的交叉编译详解
Golang 中的交叉编译 在 Golang 中,交叉编译指的是在同一台机器上生成针对不同操作系统或硬件架构的二进制文件。这在开发跨平台应用或构建特定平台的发布版本时非常有用。 交叉编译 Golang 程序的基本步骤如下: 指定目标操作系统和工具链并设置对应的…...
Python中的诡异事:不可见字符!
文章目录 前言1. 起因2. 调查3. 高能4. 释惑 前言 今天分享一件很诡异的事情,我写代码的时候遇到了不可见的字符!!! 1. 起因 今天在使用pipreqs导出项目中所依赖的库时突然报错了: pipreqs . --encodingutf-8 --forc…...
【uniapp】uniapp使用微信开发者工具制作骨架屏:
文章目录 一、效果:二、过程: 一、效果: 二、过程: 【1】微信开发者工具打开项目,生成骨架屏,将wxml改造为vue页面组件,并放入样式 【2】页面使用骨架屏组件 【3】改造骨架屏(去除…...
【UE4 RTS】06-Camera Edge Scroll
前言 本篇实现的效果是当玩家将鼠标移至屏幕边缘时,视野会相应的上下左右移动 效果 步骤 1. 打开玩家控制器“RTS_PlayerController_BP”,在类默认值中设置如下选项 新建一个宏,命名为“EdgeSroll”, 添加两个输入和三个输出&a…...
无涯教程-Perl - length函数
描述 此函数返回EXPR值的长度(以字符为单位),如果未指定,则返回$_。如果要确定相应的大小,请在数组或哈希上使用标量context。 语法 以下是此函数的简单语法- length EXPRlength返回值 此函数返回字符串的大小。 例 以下是显示其基本用法的示例代码- #!/usr/bin/perl$o…...
怎样在 CentOS 里下载 RPM 包及其所有依赖包
前几天我尝试去创建一个仅包含我们经常在 CentOS 7 下使用的软件的本地仓库。当然,我们可以使用 curl 或者 wget 下载任何软件包,然而这些命令并不能下载要求的依赖软件包。你必须去花一些时间而且手动的去寻找和下载被安装的软件所依赖的软件包。然而,我们并不是必须这样。…...
在Ubuntu上使用NFS挂载
假设要把192.16.2.101服务器上的 /home/sharedata 挂载到192.16.2.102服务器上的 /home/receive_data 一、服务端 1、安装NFS服务端 sudo apt-get install nfs-kernel-server 2、修改NFS挂载配置文件 sudo vim /etc/exports 在文件中输入 /home/sharedata 192.16.2.102(…...
复现海康威视综合安防管理平台artemis接口Spring boot heapdump内存泄露漏洞
目录 一、漏洞描述 二、影响版本 三、资产测绘 四、漏洞复现 一、漏洞描述 HIKVISION iSecure Center综合安防管理平台是一套“集成化”、“智能化”的平台,通过接入视频监控、一卡通...
哈希unordered系列介绍(上)
一.Unordered_map,Unordered_set介绍 在之前我们已经介绍过set,map,multiset等等关联式容器,它们的底层是红黑树进行模拟实现的,在查询时效率可达到 l o g 2 N log_2 N log2N,即最差情况下需要比较红黑树的高度次,当树中的节点…...
MySQL随心记第二篇
一、正则表达式篇: regular expression--> regexp 元字符: . : 单个的任意字符(默认不包含换行) \d:数字: 0-9 补集:\D \w:ascil:数字,大写字母,小写字母,以及下划线 unicode: 数字,大…...
0001nginx简介、相关模型与原理
文章目录 一. 什么是Nginx二. ngnix的一些模型1、nginx的进程模型2、worker的抢占(锁)机制模型3. nginx事件处理模型 三. nginx加载静态资源的过程 一. 什么是Nginx Nginx是一个高性能HTTP反向代理服务器,以下是nginx的相关能力 反向代理&am…...
elasticsearch简单入门语法
基本操作 创建不同的分词器 ik_smart: 极简分词 ; ik_max_word: 最细力再度分词 基本的rest命令 methodurl地址描述PUTlocalhost:9200/索引名称/类型名称/文档id创建文档(指定文档id)POSTlocalhost:9200/索引名称/类型名称创建文…...
Python自动化测试用例:如何优雅的完成Json格式数据断言
目录 前言 直接使用 优化 封装 小结 进阶 总结 资料获取方法 前言 记录Json断言在工作中的应用进阶。 直接使用 很早以前写过一篇博客,记录当时获取一个多级json中指定key的数据: #! /usr/bin/python # coding:utf-8 """ aut…...
阿里云对象存储服务OSS
1、引依赖 <dependency><groupId>com.aliyun.oss</groupId><artifactId>aliyun-sdk-oss</artifactId><version>3.15.1</version> </dependency> <dependency><groupId>javax.xml.bind</groupId><artifa…...
华为云AI开发平台ModelArts
华为云ModelArts:重塑AI开发流程的“智能引擎”与“创新加速器”! 在人工智能浪潮席卷全球的2025年,企业拥抱AI的意愿空前高涨,但技术门槛高、流程复杂、资源投入巨大的现实,却让许多创新构想止步于实验室。数据科学家…...
【根据当天日期输出明天的日期(需对闰年做判定)。】2022-5-15
缘由根据当天日期输出明天的日期(需对闰年做判定)。日期类型结构体如下: struct data{ int year; int month; int day;};-编程语言-CSDN问答 struct mdata{ int year; int month; int day; }mdata; int 天数(int year, int month) {switch (month){case 1: case 3:…...
java_网络服务相关_gateway_nacos_feign区别联系
1. spring-cloud-starter-gateway 作用:作为微服务架构的网关,统一入口,处理所有外部请求。 核心能力: 路由转发(基于路径、服务名等)过滤器(鉴权、限流、日志、Header 处理)支持负…...
FastAPI 教程:从入门到实践
FastAPI 是一个现代、快速(高性能)的 Web 框架,用于构建 API,支持 Python 3.6。它基于标准 Python 类型提示,易于学习且功能强大。以下是一个完整的 FastAPI 入门教程,涵盖从环境搭建到创建并运行一个简单的…...
全面解析各类VPN技术:GRE、IPsec、L2TP、SSL与MPLS VPN对比
目录 引言 VPN技术概述 GRE VPN 3.1 GRE封装结构 3.2 GRE的应用场景 GRE over IPsec 4.1 GRE over IPsec封装结构 4.2 为什么使用GRE over IPsec? IPsec VPN 5.1 IPsec传输模式(Transport Mode) 5.2 IPsec隧道模式(Tunne…...
【生成模型】视频生成论文调研
工作清单 上游应用方向:控制、速度、时长、高动态、多主体驱动 类型工作基础模型WAN / WAN-VACE / HunyuanVideo控制条件轨迹控制ATI~镜头控制ReCamMaster~多主体驱动Phantom~音频驱动Let Them Talk: Audio-Driven Multi-Person Conversational Video Generation速…...
视觉slam十四讲实践部分记录——ch2、ch3
ch2 一、使用g++编译.cpp为可执行文件并运行(P30) g++ helloSLAM.cpp ./a.out运行 二、使用cmake编译 mkdir build cd build cmake .. makeCMakeCache.txt 文件仍然指向旧的目录。这表明在源代码目录中可能还存在旧的 CMakeCache.txt 文件,或者在构建过程中仍然引用了旧的路…...
Java数值运算常见陷阱与规避方法
整数除法中的舍入问题 问题现象 当开发者预期进行浮点除法却误用整数除法时,会出现小数部分被截断的情况。典型错误模式如下: void process(int value) {double half = value / 2; // 整数除法导致截断// 使用half变量 }此时...
在Mathematica中实现Newton-Raphson迭代的收敛时间算法(一般三次多项式)
考察一般的三次多项式,以r为参数: p[z_, r_] : z^3 (r - 1) z - r; roots[r_] : z /. Solve[p[z, r] 0, z]; 此多项式的根为: 尽管看起来这个多项式是特殊的,其实一般的三次多项式都是可以通过线性变换化为这个形式…...
python爬虫——气象数据爬取
一、导入库与全局配置 python 运行 import json import datetime import time import requests from sqlalchemy import create_engine import csv import pandas as pd作用: 引入数据解析、网络请求、时间处理、数据库操作等所需库。requests:发送 …...
