Android 性能优化之布局优化
文章目录
- Android 性能优化之布局优化
- 绘制原理
- 双缓冲机制
- 布局加载原理
- 检测耗时
- 常规方式
- AOP方式
- 获取控件加载耗时
- 布局优化
- AsyncLayoutInflater方案
- Compose方案
- 减少布局层级和复杂度
- 避免过度绘制
Android 性能优化之布局优化
绘制原理
- CPU:负责执行应用层的measure、layout、draw等操作,将绘制的数据交给GPU处理。
- GPU:进一步处理数据,并缓存数据。
- 屏幕:由一个个像素点组成的,以固定的频率(16.6ms,1秒60帧)从缓冲区获取数据填充像素点。
双缓冲机制
GPU 向缓冲区写入数据的同时,屏幕也在向缓冲区读取数据,可能会导致屏幕上就会出现一部分是前一帧的画面,一部分是另一帧的画面。
因此 Android 系统使用双缓冲机制,GPU 只向Back Buffer
中写入绘制数据,且 GPU 会定期交换Back Buffer
和Frame Buffer
,交换的频率也是60次/秒,这就与屏幕的刷新频率保持了同步。
GPU 向 Back Buffer 写入数据时,系统会锁定 Back Buffer,如果布局比较复杂或设备性能较差时,CPU 不能保证16.6ms内完成计算,因此到了 GPU 交换两个 Buffer 的时间点,GPU 就会发现 Back Buffer 被锁定了,会放弃这次交换,也就是掉帧。
布局加载原理
- 解析XML文件,涉及 IO 操作。
- 通过 createViewFromTag() 创建View,用到了反射机制。
检测耗时
常规方式
public class MainActivity extends AppCompatActivity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);long start = System.currentTimeMillis();setContentView(R.layout.activity_main);long time = System.currentTimeMillis() - start;Log.e("TAG", "setContentView耗时:" + time);}
}
AOP方式
使用第三方框架:
https://github.com/FlyJingFish/AndroidAOP
定义切面类:
@AndroidAopMatchClassMethod(targetClassName = "androidx.appcompat.app.AppCompatActivity",methodName = {"setContentView"},type = MatchType.SELF
)
public class MatchSetContentView implements MatchClassMethod {@Nullable@Overridepublic Object invoke(@NonNull ProceedJoinPoint proceedJoinPoint, @NonNull String methodName) {Class<?> targetClass = proceedJoinPoint.getTargetClass();long start = System.currentTimeMillis();proceedJoinPoint.proceed();long time = System.currentTimeMillis() - start;Log.e("TAG", targetClass.getSimpleName() + "#" + methodName + "耗时:" + time);return null;}
}
获取控件加载耗时
public class MainActivity extends AppCompatActivity {@Overrideprotected void onCreate(Bundle savedInstanceState) {LayoutInflaterCompat.setFactory2(getLayoutInflater(), new LayoutInflater.Factory2() {@Nullable@Overridepublic View onCreateView(@Nullable View parent, @NonNull String name, @NonNull Context context, @NonNull AttributeSet attrs) {long start = System.nanoTime();View view = getDelegate().createView(parent, name, context, attrs);Log.e("TAG", name + "耗时:" + (System.nanoTime() - start) + "ns");return view;}@Nullable@Overridepublic View onCreateView(@NonNull String name, @NonNull Context context, @NonNull AttributeSet attrs) {return null;}});super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);}
}
布局优化
优化思路:
- IO 优化。
- 反射优化。
AsyncLayoutInflater方案
AsyncLayoutInflater 是 Android 提供的一个异步加载布局的类,它允许在 UI 线程之外加载和解析 XML 布局文件,减少主线程的阻塞,从而提高应用的响应性能。
添加依赖库:
implementation "androidx.asynclayoutinflater:asynclayoutinflater:1.0.0"
使用:
new AsyncLayoutInflater(this).inflate(R.layout.activity_main, null, new AsyncLayoutInflater.OnInflateFinishedListener() {@Overridepublic void onInflateFinished(@NonNull View view, int resid, @Nullable ViewGroup parent) {setContentView(view);}
});
缺点:
- 兼容性一般。
- 牺牲了易用性。
Compose方案
- 新一代UI,声明式UI。
- 去掉了 XML。
减少布局层级和复杂度
- 使用 ConstraintLayout 可以实现扁平化布局,减少层级。
- 使用 RelativeLayout 减少嵌套。
- 嵌套的 LinearLayout 尽量少用 weight 属性,因为 weight 会重复测量。
- 使用 merge 标签减少布局层级。
- 使用 ViewStub 标签进行延迟加载。
- 使用 include 标签提取复用布局。
避免过度绘制
- 去掉多余的背景色,减少复杂 shape 的使用。
- 避免层级叠加。
- 自定义 View 使用 clipRect 屏蔽被遮盖 View 绘制。
相关文章:

Android 性能优化之布局优化
文章目录 Android 性能优化之布局优化绘制原理双缓冲机制布局加载原理检测耗时常规方式AOP方式获取控件加载耗时 布局优化AsyncLayoutInflater方案Compose方案减少布局层级和复杂度避免过度绘制 Android 性能优化之布局优化 绘制原理 CPU:负责执行应用层的measure…...

TCP 握手数据流
这张图详细描述了 TCP 握手过程中,从客户端发送 SYN 包到服务器最终建立连接的整个数据流转过程,包括网卡、内核、进程中的各个环节。下面对每个步骤进行详细解释: 客户端到服务器的初始连接请求 客户端发送 SYN 包: 客户端发起…...
MDA协议
MDA协议通常指消息摘要算法(Message Digest Algorithm),在计算机安全和密码学中被广泛用于数据完整性验证和认证。以下是对MDA协议的详细介绍: 1. 概述 MDA协议是一类哈希函数,用于生成固定长度的消息摘要或哈希值。…...

always块敏感列表的相关报错,
在综合的时候,报错如下 Synthesis synth_1 [Synth 8-91] ambiguous clock in event control ["E:/FPGA/FPGA_project/handwrite_fft/handwrite_fft.srcs/sources_1/new/reg_s2p.v":140] 猜测报错原因(暂时没有时间寻找原因,后续在…...
STM32空闲中断处理串口接受数据
1、检测到空闲线路中断也叫做空闲中断,意思是串口接收完1字节数据后,数据先保持高电平(空闲)的时间超过1字节数据所用的时间,则被判定为空闲中断。 2、HAL库中操作空闲中断的宏是 (1)_HAL_UAR…...

oak相机使用oak官网方式标定
目录 一、depthai ROS驱动 一、depthai ROS驱动 (1)驱动下载地址:2. C 开发快速上手 — DepthAI Docs 0.3.0.0 documentation sudo apt install ./depthai_2.17.1_arm64.deb //运行 Python3 utilities/cam_test.py -mres 400 -cams rgb,m …...

打造高效能“园区企业服务平台”,让企业更好更快发展!
近年来,随着我国经济的快速发展,各地产业园区建设如火如荼,成为区域经济的支柱,如果说园区是区域经济的支柱,企业则是园区的血液,给园区带来生命力,为园区发展提供着动力,各地政府…...

【常见开源库的二次开发】基于openssl的加密与解密——openssl认识与配置(一)
目录: 目录: 一、什么是openssl? 二、所需要具备的开发工具 三、Windows上编译OpenSSL3.0 四、Linux编译openssl3.0 一、什么是openssl? OpenSSL 是一个开源的软件库,它提供了一系列加密工具和协议,主要用…...
前端时间格式传入后端负载里面没有东西
我是因为没有将时间值格式化,所有负载没有东西 <el-col :md"6"><el-form-item label"创建时间" prop"createTime"><el-date-picker v-model"queryParams.createTime" type"date" change"ha…...

BUCK电源芯片,电气参数,极限参数,工作特性,引脚功能
概述 在应用DC-DC开关电源芯片时,通常需要关注以下参数,同步与非同步,输入电压,输入电流,输出电压,输出电流,输入输出电容的选择;mosfet选型,电感选型,功耗&a…...
学习小记-使用Redis的令牌桶算法实现分布式限流
在介绍令牌桶算法前先介绍一下漏桶算法(Leaky Bucket) 漏桶算法(Leaky Bucket) 漏桶算法是一种固定容量的容器模型,它通过控制数据流入和流出的速度来限制数据的传输速率。漏桶算法的主要特点包括: 固定…...

electron + express 实现 vue 项目客户端部署
写在前面 作为一个前端程序员,如何实现从前端到客户端的跨越,可能是一个很难实现的事。但客户需求千奇百怪,偶尔遇到一个非要客户端的,如何应对? 那Electron可能真是你福音。具体它有哪些功能,可自行官网…...

千万慎投!自引率高达93%!这16本On hold正处于高危状态,无法检索,剔除岌岌可危中!近四年镇压期刊“出狱”情况一览
本周投稿推荐 SCI • 能源科学类,1.5-2.0(25天来稿即录) • CCF推荐,4.5-5.0(2天见刊) • 生物医学制药类(2天逢投必中) EI • 各领域沾边均可(2天录用)…...

【数据结构】排序——快速排序
前言 本篇博客我们继续介绍一种排序——快速排序,让我们看看快速排序是怎么实现的 💓 个人主页:小张同学zkf ⏩ 文章专栏:数据结构 若有问题 评论区见📝 🎉欢迎大家点赞👍收藏⭐文章 目录 …...
Matlab 怎么查找矩阵中所有0的数据并赋值
index find(X40); X4(index)57.71527;...
开发一个HTTP模块
开发一个HTTP模块 HTTP模块的数据结构ngx_module_t模块的数据结构ngx_http_module_t数据结构ngx_command_s 数据结构 定义一个HTTP模块处理用户请求返回值获取URI和参数方法名URIURL协议版本 获取HTTP头获取HTTP包体 发送响应发送HTTP头发送内存中的字符串作为包体返回一个Hell…...
vue2实现复制,粘贴功能,使用vue-clipboard2插件
一、需求说明 在项目中 点击按钮 复制 某行文本是很常见的 应用场景, 在 Vue 项目中实现 复制功能 需要借助 vue-clipboard2 插件。 二、代码实现 1、安装 vue-clipboard2 依赖 ( 出现错误的话,可以试试切换成淘宝镜像源 npm config set r…...

【软件测试】 1+X初级 功能测试试题
【软件测试】 1X初级 功能测试试题 普通员工登录系统,在“个人信息维护”模块,可以查看和维护个人信息。个人信息维护需求包括用户(UI)页面、业务规则两部分。 UI 界面 个人信息维护 修改基本信息 业务规则 1. 个人信息维护页面…...

zynq启动和程序固化流程
普通FPGA启动 FPGA的启动方式主要包含主动模式、被动模式和JTAG模式。 主动模式(AS模式) 当FPGA器件上电时,它作为控制器从配置器件EPCS中主动发出读取数据信号,并将EPCS的数据读入到自身中,实现对FPGA的编程。这种…...

CSS3实现彩色变形爱心动画【附源码】
随着前端技术的发展,CSS3 为我们提供了丰富的动画效果,使得网页设计更加生动和有趣。今天,我们将探讨如何使用 CSS3 实现一个彩色变形爱心加载动画特效。这种动画不仅美观,而且可以应用于各种网页元素,比如加载指示器或…...

大话软工笔记—需求分析概述
需求分析,就是要对需求调研收集到的资料信息逐个地进行拆分、研究,从大量的不确定“需求”中确定出哪些需求最终要转换为确定的“功能需求”。 需求分析的作用非常重要,后续设计的依据主要来自于需求分析的成果,包括: 项目的目的…...
MySQL 隔离级别:脏读、幻读及不可重复读的原理与示例
一、MySQL 隔离级别 MySQL 提供了四种隔离级别,用于控制事务之间的并发访问以及数据的可见性,不同隔离级别对脏读、幻读、不可重复读这几种并发数据问题有着不同的处理方式,具体如下: 隔离级别脏读不可重复读幻读性能特点及锁机制读未提交(READ UNCOMMITTED)允许出现允许…...

Redis相关知识总结(缓存雪崩,缓存穿透,缓存击穿,Redis实现分布式锁,如何保持数据库和缓存一致)
文章目录 1.什么是Redis?2.为什么要使用redis作为mysql的缓存?3.什么是缓存雪崩、缓存穿透、缓存击穿?3.1缓存雪崩3.1.1 大量缓存同时过期3.1.2 Redis宕机 3.2 缓存击穿3.3 缓存穿透3.4 总结 4. 数据库和缓存如何保持一致性5. Redis实现分布式…...

tree 树组件大数据卡顿问题优化
问题背景 项目中有用到树组件用来做文件目录,但是由于这个树组件的节点越来越多,导致页面在滚动这个树组件的时候浏览器就很容易卡死。这种问题基本上都是因为dom节点太多,导致的浏览器卡顿,这里很明显就需要用到虚拟列表的技术&…...
Android第十三次面试总结(四大 组件基础)
Activity生命周期和四大启动模式详解 一、Activity 生命周期 Activity 的生命周期由一系列回调方法组成,用于管理其创建、可见性、焦点和销毁过程。以下是核心方法及其调用时机: onCreate() 调用时机:Activity 首次创建时调用。…...

Selenium常用函数介绍
目录 一,元素定位 1.1 cssSeector 1.2 xpath 二,操作测试对象 三,窗口 3.1 案例 3.2 窗口切换 3.3 窗口大小 3.4 屏幕截图 3.5 关闭窗口 四,弹窗 五,等待 六,导航 七,文件上传 …...
MySQL JOIN 表过多的优化思路
当 MySQL 查询涉及大量表 JOIN 时,性能会显著下降。以下是优化思路和简易实现方法: 一、核心优化思路 减少 JOIN 数量 数据冗余:添加必要的冗余字段(如订单表直接存储用户名)合并表:将频繁关联的小表合并成…...
探索Selenium:自动化测试的神奇钥匙
目录 一、Selenium 是什么1.1 定义与概念1.2 发展历程1.3 功能概述 二、Selenium 工作原理剖析2.1 架构组成2.2 工作流程2.3 通信机制 三、Selenium 的优势3.1 跨浏览器与平台支持3.2 丰富的语言支持3.3 强大的社区支持 四、Selenium 的应用场景4.1 Web 应用自动化测试4.2 数据…...
Spring AI Chat Memory 实战指南:Local 与 JDBC 存储集成
一个面向 Java 开发者的 Sring-Ai 示例工程项目,该项目是一个 Spring AI 快速入门的样例工程项目,旨在通过一些小的案例展示 Spring AI 框架的核心功能和使用方法。 项目采用模块化设计,每个模块都专注于特定的功能领域,便于学习和…...
提升移动端网页调试效率:WebDebugX 与常见工具组合实践
在日常移动端开发中,网页调试始终是一个高频但又极具挑战的环节。尤其在面对 iOS 与 Android 的混合技术栈、各种设备差异化行为时,开发者迫切需要一套高效、可靠且跨平台的调试方案。过去,我们或多或少使用过 Chrome DevTools、Remote Debug…...