布局性能优化:安卓开发者不可错过的性能优化技巧

news2025/1/17 2:55:38

作者:麦客奥德彪

当我们开发Android应用时,布局性能优化是一个必不可少的过程。一个高效的布局能够提高用户体验,使应用更加流畅、响应更加迅速,而低效的布局则会导致应用的运行变得缓慢,甚至出现卡顿、崩溃等问题,影响用户体验。在开发中,布局优化不仅需要考虑到UI设计的美观性和易用性,还需要关注布局的性能,避免出现因视图过多、嵌套过深、图片过大等问题导致的性能瓶颈。通过对布局进行优化,可以显著提高应用的性能和用户体验,减少应用的CPU和内存占用,加快应用的启动和响应速度,降低应用的耗电量,从而提高应用的稳定性和可靠性。

布局性能优化对于提高Android应用的质量和竞争力是至关重要的。在实际开发中,我们需要根据具体的业务场景和设计要求,结合布局优化的最佳实践,逐步提升应用的布局性能,为用户带来更好的体验。

布局为什么会有性能问题呢

那需要了解一下Android View的渲染机制,Android渲染机制是指Android系统中用于显示界面的工作流程。它包括视图树的构建、测量、布局和绘制四个过程。

他们的大致流程是

  1. 构建视图树(View Hierarchy):在应用启动时,Android系统会根据布局文件中定义的View、ViewGroup和其他组件创建一个视图树。视图树是根据xml进行解析的。
  2. 测量(Measure):在测量过程中,系统会遍历视图树,并计算每个视图的大小和位置
  3. 布局(Layout):在布局过程中,系统会根据视图树中每个视图的测量结果,确定每个视图的大小和位置,并将其放置在正确的位置上
  4. 绘制(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。这种操作会导致内存消耗过高的。

常见的检测布局性能工具

  1. Hierarchy Viewer工具:Hierarchy Viewer工具可以帮助开发者分析应用程序的视图层次结构,找出可能存在的性能问题。在Hierarchy Viewer中,可以查看应用程序的视图层次结构,以及每个视图的绘制时间、测量时间和布局时间等性能指标。
  2. TraceView工具:TraceView工具可以帮助开发者分析应用程序的性能问题,包括布局性能问题。在TraceView中,可以查看应用程序的方法调用链和执行时间等信息,以及每个方法的CPU使用率、内存消耗等性能指标。
  3. UI性能分析器:Android Studio中内置了UI性能分析器,可以帮助开发者分析应用程序的UI性能问题,包括布局性能问题。在UI性能分析器中,可以查看应用程序的渲染时间、FPS、布局时间等性能指标,并根据性能指标分析应用程序的性能问题。
  4. 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

  1. 开机Init 进程
  2. 开机启动 Zygote 进程
  3. 开机启动 SystemServer 进程
  4. Binder 驱动
  5. AMS 的启动过程
  6. PMS 的启动过程
  7. Launcher 的启动过程
  8. Android 四大组件
  9. Android 系统服务 - Input 事件的分发过程
  10. Android 底层渲染 - 屏幕刷新机制源码分析
  11. Android 源码分析实战

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/869040.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

植被利用了多少陆地降水?

降水部分被植被利用&#xff0c;部分转化为河水流量。量化植被直接使用的水量对于解读气候变化的影响至关重要。 新提出的模型的预测与之前的结果进行了比较。资料来源&#xff1a;AGU Advances 水是地球的重要组成部分&#xff0c;因此&#xff0c;了解大尺度的水平衡及其建模…

【Rust】Rust学习 第十章泛型、trait 和生命周期

泛型是具体类型或其他属性的抽象替代。我们可以表达泛型的属性&#xff0c;比如他们的行为或如何与其他泛型相关联&#xff0c;而不需要在编写和编译代码时知道他们在这里实际上代表什么。 之后&#xff0c;我们讨论 trait&#xff0c;这是一个定义泛型行为的方法。trait 可以…

Springboot04--vue前端部分+element-ui

注意点&#xff1a; 这边v-model和value的区别&#xff1a;v-model是双向绑定的&#xff0c;value是单向绑定 li的key的问题 vue的组件化开发&#xff1a; 1. NPM&#xff08;类似maven&#xff0c;是管理前段代码的工具&#xff09; 安装完之后可以在cmd里面使用以下指令 2.…

带你认识储存以及数据库新技术演进

01经典案例 1.0 潜在问题 02存储&数据库简介 2.1 存储器层级架构 2.1 数据怎么从应用到存储介质 2.1 RAID技术 2.2 数据库 数据库分为 关系型数据库 和 非关系型数据库 2.2.2 非关系型 2.2.1 关系型 2.3 数据库 vs 经典存储-结构化数据管理 2.3.1 数据库 vs 经典存储-事务能…

c++ static

static 成员 声明为static的类成员称为类的静态成员&#xff0c;用static修饰的成员变量&#xff0c;称之为静态成员变量&#xff1b;用 static修饰的成员函数&#xff0c;称之为静态成员函数。静态成员变量一定要在类外进行初始化。 看看下面代码体会一下: //其他类 class …

​运行paddlehub报错,提示:UnicodeDecodeError: ‘gbk‘ codec can‘t decode byte…**​

我在windows11环境下运行paddlehub报错&#xff0c;提示&#xff1a;UnicodeDecodeError: ‘gbk‘ codec can‘t decode byte…** 参考篇文字的解决方案&#xff1a;window10下运行项目报错&#xff1a;UnicodeDecodeError: ‘gbk‘ codec can‘t decode byte...的解决办法_uni…

C语言——将一串字符进行倒序

//将一串字符进行倒序 #include<stdio.h> #define N 6 int main() {int a[N]{0,1,2,3,4,5};int i,t;printf("原数组数值&#xff1a; ");for(i0;i<N;i)printf("%d",a[i]);for(i0;i<N/2;i){ta[i];a[i]a[N-1-i];a[N-1-i]t;}printf("\n排序…

Xilinx DDR3学习总结——3、MIG exmaple仿真

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 Xilinx DDR3学习总结——3、MIG exmaple例程仿真 前言仿真 前言 前面我们直接把exmaple例程稍加修改就进行了抢先上板测试&#xff0c;证明了MIG模块工作时正常的&#xff0…

SWIG使用方法

安装 下载 swigwin软件包&#xff0c;解压到合适的位置&#xff0c;然后将路径添加到环境变量即可。 编写C代码 //vector.hpp class Vector { private:int x;int y; public:Vector(int,int);double abs();void display(); };//vector.cpp #include "vector.hpp" …

C语言 ——指针数组与数组指针

目录 一、二维数组 二、指针数组 &#xff08;1&#xff09;概念 &#xff08;2&#xff09;书写方式 &#xff08;3&#xff09;指针数组模拟二维数组 三、数组指针 &#xff08;1&#xff09;概念 &#xff08;2&#xff09;使用数组指针打印一维数组 &#xff08;3&a…

网络协议栈-基础知识

1、分层模型 1.1、OSI七层模型 1、OSI&#xff08;Open System Interconnection&#xff0c;开放系统互连&#xff09;七层网络模型称为开放式系统互联参考模型 &#xff0c;是一个逻辑上的定义&#xff0c;一个规范&#xff0c;它把网络从逻辑上分为了7层。 2、每一层都有相关…

【C语言】分支语句(选择结构)详解

✨个人主页&#xff1a; Anmia.&#x1f389;所属专栏&#xff1a; C Language &#x1f383;操作环境&#xff1a; Visual Studio 2019 版本 目录 什么是分支语句&#xff1f; if语句 if if - else单分支 if - else if - else ...多分支 if - if嵌套 switch语句 基本语…

HackRF One Block Diagram

HackRF One r1-r8 Block Diagram HackRF One r9 Block Diagram

FPGA 之 xilinx DDS IP相位控制字及频率控制字浅析

浅析相位环在Xilinx DDS中的理解 本文仅为个人理解之用; 相关仿真结果如下:

Qt5.9.4搭建安卓环境-Qt for Android

目录 需要安装以下内容&#xff1a;安装JDK设置环境变量安装剩余文件 使用新建文件 可能出现的问题第一种解决方法&#xff1a; 第二种解决方法 需要安装以下内容&#xff1a; 下载地址&#xff1a; https://www.qter.org/portal.php?modview&aid10 很多Qt开发会用到的环…

理解-面向对象

目录 对象&#xff1a; 举例&#xff1a; 封装: 好处: 继承: 多态&#xff1a; 类和对象之间的关系 对象&#xff1a; 把一个东西看成对象&#xff0c;我们就可以孤立的审查它的性质&#xff0c;行为&#xff0c;进而研究它和其他对象的关系。 对象是一个应用系统中用…

探索极限:利用整数或字符串操作找出翻转后的最大数字

本篇博客会讲解力扣“1323. 6 和 9 组成的最大数字”的解题思路&#xff0c;这是题目链接。 对于这道题目&#xff0c;我会讲解2种解题思路&#xff0c;分别是直接操作整数&#xff0c;和利用字符串操作。希望大家通过本题学习关于整数和字符串的技巧。 显然&#xff0c;这道题…

如何在 .NET Core WebApi 中处理 MultipartFormDataContent 中的文件

问题描述# 上图示例展示了用户通过 IOS 客户端发送请求时&#xff0c;对应后端接口接收到的 Request 内容。从请求内容的整体结果&#xff0c;我们可以看出这是一个 multipart/form-data 的数据格式&#xff0c;由于这种数据是由多个 multipart section 组成&#xff0c;所以我…

ELK常见部署架构以及出现的问题及解决方案

ELK常见部署架构以及出现的问题及解决方案 ELK 已经成为目前最流行的集中式日志解决方案&#xff0c;它主要是由Beats 、Logstash 、Elasticsearch 、 Kibana 等组件组成&#xff0c;来共同完成实时日志的收集&#xff0c;存储&#xff0c;展示等一站式的解决方案。本文将会介…

无情被裁的后续来了

关注、星标公众号&#xff0c;直达精彩内容 来源&#xff1a;技术让梦想更伟大作者&#xff1a;不生气 大家好&#xff0c;给大家分享一个案例&#xff0c;收集好证据&#xff0c;劳动仲裁吧 &#xff0c;裁员时候老板打感情牌&#xff0c;员工呢坚持付出就得回报按照程序来。…