【Android】性能优化之内存、网络、布局、卡顿、安装包、启动速度优化

欢迎来到 Android 开发老生常谈的性能优化篇,本文将性能优化划分为内存、网络、布局、卡顿、安装包、启动速度七块,从这七块优化出发,阐述优化的 Application 的方式。

目录

  • 内存优化
    • 避免内存泄漏
    • 使用内存分析工具
    • 优化数据结构和算法
    • 数据缓存
    • 避免频繁的 GC
  • 网络优化
    • 合并接口请求,减少请求次数
    • 使用网络缓存
    • 使用合适的数据格式
    • 使用合适的网络库
    • 后台同步
    • 预加载
    • 使用持久连接
    • 优化图片加载
    • 使用前检测网络
  • 布局优化
    • 1、减少布局嵌套
    • 2、减少 wrap-content 的使用
    • 3、使用 include、merge、ViewStub,重复布局复用
  • 卡顿优化
    • 造成卡顿的原因
      • 主线程阻塞
      • 内存泄漏
      • 布局过于复杂
      • Bitmap对象过大
      • 频繁的GC
      • 动画效果处理不当
    • 如何避免卡顿问题
      • 避免在主线程中执行耗时操作
      • 优化布局
      • 处理内存泄漏
      • 优化Bitmap的使用
      • 减少GC的触发
  • 安装包优化
    • 资源优化
      • 1、按需添加第三方库,避免引入重复库。
      • 2、 png转svg,再使用svg转成vector格式。
      • 3、 删除多余的so库。
      • 4、 删除多余的 `mipmap` 文件夹。
      • 5、 删除未使用到的资源文件。
      • 6、动态加载.so文件。
      • 7、使用插件化。
    • 代码混淆
  • 启动速度优化
    • App Startup 优化初始化速度
    • 懒加载
      • ViewStup 按需加载布局
      • Paging 分页
      • ViewPager 2 翻页
    • 预加载
    • 伪加载
      • 设置启动页
    • 代码优化
      • 使用 adb 命令查看启动 Activity 时间
      • 使用 Profile 查看 Activity 方法耗时,对其进行优化
    • WorkManager 后台保活
  • 课外小知识
    • 应用启动状态
      • 冷启动
      • 温启动
      • 热启动

内存优化

在 Android 中,内存优化通常指的是 运行内存优化。运行内存优化 主要关注如何有效地使用和管理应用程序的 RAM (Random Access Memory) 使用,以提高性能,减少延迟,并防止应用程序因为消耗过多内存而被系统杀死。

避免内存泄漏

内存泄漏是指应用程序分配了内存,但未能释放。这会导致应用程序消耗的内存随着时间的推移而增加,可能导致应用程序崩溃或系统性能下降。

使用内存分析工具

Android Studio 提供了一些工具,如 Memory Profiler,可以帮助开发者分析和理解应用程序的内存使用情况。

优化数据结构和算法

使用更有效的数据结构和算法可以减少内存使用。

数据缓存

合理使用 数据库、网络、图片缓存数据,可以减少不必要的数据、重复数据的存储,减少数据创建和销毁的开销,此外,还可以提高数据的访问速度。

避免频繁的 GC

垃圾回收 (Garbage Collection 简称 GC) ,频繁的垃圾回收会影响应用程序的性能。可以通过减少对象的创建和销毁,以及使用对象池等技术来减少垃圾回收的频率。

网络优化

合并接口请求,减少请求次数

尽可能地减少网络请求次数,可以通过合并请求、使用批量接口等方式实现。

使用网络缓存

对于一些不经常变动的数据,可以使用缓存来减少网络请求。例如,可以使用 HTTP 缓存、数据库缓存或者内存缓存。

使用合适的数据格式

例如,对于大量的数据,可以使用 Protobuf 而不是 JSON,因为 Protobuf 更加紧凑,可以减少数据的大小,从而减少网络传输的时间。

使用合适的网络库

使用 OkHttpRetrofit 等网络库,它们内部已经做了很多优化。

后台同步

对于一些不需要立即返回结果的操作,可以使用后台同步,例如使用 WorkManager 或者 JobScheduler

预加载

对于一些用户可能需要的数据,可以提前进行加载。

使用持久连接

使用 HTTP2,它们支持多路复用,可以减少连接的建立和关闭的开销。

优化图片加载

对于图片,可以使用合适的格式和大小,还可以使用图片加载库,例如 Glide 或者 Picasso,它们内部已经做了很多优化。

使用前检测网络

在进行网络请求前,先检测网络状态,如果网络不可用,那么可以立即返回错误,而不是等待超时。

布局优化

1、减少布局嵌套

2、减少 wrap-content 的使用

3、使用 include、merge、ViewStub,重复布局复用

卡顿优化

在 Android 系统中,每一秒屏幕刷新速度为 60 帧(FPS),人类眼睛舒适放松时的可视帧率是 24 帧,当某个加载中的界面每秒刷新低于 24 帧时,就会感觉到卡顿。但当屏幕没有绘制需求时,即屏幕的显示的界面为静止时,帧率为 0。

造成卡顿的原因

主线程阻塞

如果在主线程(UI线程)中执行了耗时的操作,如网络请求、数据库操作等,会导致UI更新延迟,从而引发卡顿。

内存泄漏

如果应用中存在内存泄漏,可能会导致内存占用过高,从而引发卡顿。

布局过于复杂

如果布局层级过深或者布局过于复杂,可能会导致布局渲染时间过长,从而引发卡顿。

Bitmap对象过大

如果Bitmap对象过大,可能会导致内存占用过高,从而引发卡顿。

频繁的GC

垃圾回收 (Garbage Collection 简称 GC) 过程需要消耗系统资源,如果频繁触发,可能会导致应用性能下降,出现卡顿现象。

动画效果处理不当

如何避免卡顿问题

避免在主线程中执行耗时操作

可以使用线程、协程、AsyncTask等技术将耗时操作移至后台执行。

优化布局

尽量减少布局的层级,避免过度绘制,使用更高效的 View 或 ViewGroup。

处理内存泄漏

使用 LeakCanary 等工具帮助找到并处理内存泄漏。

优化Bitmap的使用

尽量不要使用过大的 Bitmap,使用合适的压缩格式和分辨率,及时回收不再使用的Bitmap

减少GC的触发

尽量减少内存抖动,避免频繁的对象创建和销毁。 内存抖动 (Memory Churn) 是指应用程序在短时间内频繁地创建和销毁对象,这种行为会导致垃圾回收器 (Garbage Collector) 频繁地运行,从而消耗大量的CPU资源,可能导致应用程序的性能下降,出现卡顿现象。

以上只是一些可能的原因,具体的原因需要通过性能分析工具如 Android ProfilerBlockCanarySystrace 等进行分析。

往期文章👉【Android】测试方法汇总,助力打造完美应用

安装包优化

资源优化

1、按需添加第三方库,避免引入重复库。

2、 png转svg,再使用svg转成vector格式。

3、 删除多余的so库。

删除多余的so库,执行这一操作的前提是:程序所运行的系统 CPU 架构固定是 Android CPU 架构中的某一个。例如:部分第三方提供的 so 库是包含了 armeabiarmeabi-v71arm64-v8ax86 等库文件,如果你的程序只运行在 armeabi CPU 架构上,则可以把其它的 so 库文件删除。

4、 删除多余的 mipmap 文件夹。

一般图标资源使用 mipmap-xhdpi 足够用了,更大的屏幕则使用 mipmap-xxhdpimipmap-xxxhdpi 的分辨率,已经使用 mipmap-xhdpi 或其它更大分辨率的程序,应删除比它小的分辨率文件。

5、 删除未使用到的资源文件。

可通过 Android Studio 菜单栏的 RefactorRemove Unused Resources 功能一键移除未被使用的 drawablemipmaplayout 以及 colors.xmlstrings.xml 文件里面的 colorstring

6、动态加载.so文件。

.so 文件可以在用户安装应用到手机后再从服务器上下载到手机的 data 目录下,加载的时候使用绝对路径在 static 关键字里加载。

static {System.loadLibrary("so文件")
}

参考文章
1、Android 应用资源概述

7、使用插件化。

插件化技术支持动态加载代码和动态加载资源,把 Application 的一部分分离出来,对于业务庞大的项目非常有用,极大的分解了 Application 的大小。但又因为插件化需要一定的技术保障和服务端的系统支持,有一定的风险,建议酌情选择。

代码混淆

代码混淆(Obfuscation)是将计算机程序的源代码或机器代码,转换成功能上等价,但是难于阅读和理解的形式的行为。简单来说,就是简化函数名、变量、常量名称,通过减少字符数以达到减小安装包大小的方式。

启用混淆只需要打开 Android 项目,在 Application Model 下中找到 build.gradle,在该文件添加如下配置即可开启混淆:

android {// 打包 release 包时执行release {// 启用混淆,默认使用 R8 编译器minifyEnabled true// 资源压缩shrinkResources true// 定义 自定义混淆规则的文件proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'}}
}

上面混淆的方式仅适用于代码简单、封装少的项目。项目复杂还请自定义混淆规则,详情请查看往期文章👉【Android】App攻防之代码混淆

启动速度优化

App Startup 优化初始化速度

App Startup 是 Android 官方推出的一个应用程序启动时初始化组件的库。开发人员可以使用 App Startup 来简化启动序列并显式设置初始化顺序。

详情请看👉 App Startup

懒加载

懒加载是一种延迟加载的策略,它指的是在需要时才进行加载和初始化,而不是在应用程序启动或页面加载时就提前加载。这种策略通常用于延迟加载大型资源或组件,以减少启动时间和内存占用。

ViewStup 按需加载布局

详情请看👉 ViewStup

Paging 分页

详情请看👉 Paging

ViewPager 2 翻页

详情请看👉 ViewPager 2

预加载

预加载是在应用程序启动或特定页面加载之前提前加载和准备数据、资源或组件。这有助于提高应用程序的性能和响应速度,因为一些必要的内容已经被提前加载到内存中,而不是等到用户请求时再进行加载。

伪加载

伪加载是一种虚假的加载行为,通常用于模拟加载过程而不实际进行真正的加载。这种策略可以用于创建加载动画或展示加载状态,以提升用户体验,但实际上并没有进行真实的加载操作。

设置启动页

给 app 添加启动页,这应该是最常见的实现伪加载的方式了。当应用启动页播放完成跳转到首页时,你能很明显的感觉到,app 比没有使用启动页之前变得更“流畅”了。

设置启动页参考文章 👉 Android—启动页+闪屏页

其它启动速度优化的方法:
1、尽量不要在ApplicationonCreate中写初始化代码
2、减少静态类、静态方法、静态函数的使用,尽量做到用时再初始化

代码优化

使用 adb 命令查看启动 Activity 时间

在 Android 中,我们可以通过 adb 命令:adb shell am start -W packageName/packageName.ActivityName 获取到启动该 Activity 所消耗的时间,如下:

 E:\Projects\StepDemo> adb shell am start -W com.binyouwei.demo/com.binyouwei.demo.MainActivityStarting: Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] cmp=com.binyouwei.demo/.MainActivity }
Status: ok
Activity: com.binyouwei.demo/.MainActivity
ThisTime: 522
TotalTime: 522
WaitTime: 525
Complete

在上方,我输入了 adb shell am start -W com.binyouwei.demo/com.binyouwei.demo.MainActivity ,系统给我响应了一大串的字符,其中的含义如下:
ThisTime:指定的 activity 启动耗时。
TotalTime:应用自身启动耗时 = ThisTime + 应用 Application 等资源启动时间
WaitTime:系统启动应用耗时 = TotalTime + 系统资源启动时间

使用 Profile 查看 Activity 方法耗时,对其进行优化

使用参考文章👉Android Studio 中 CPU Profiler 系统性能分析工具的使用

WorkManager 后台保活

使用 WorkManager 实现后台保活,当应用处于后台时,应用所占的内存不会被系统完全回收,再次启动应用相较于第一次启动会更快。

课外小知识

应用启动状态

冷启动

冷启动是指应用程序从头开始启动的过程,这意味着应用程序的进程被终止,用户点击应用图标重新启动应用。在冷启动过程中,应用需要重新创建进程、初始化应用程序和加载 UI 界面。

温启动

温启动是指应用程序在后台保持活动状态并且重新进入前台时的启动方式。在温启动过程中,应用程序的进程仍然存在,但需要重新初始化和加载 UI 界面。

热启动

热启动是指应用程序在后台保持活动状态并且重新进入前台时的快速启动方式。在热启动过程中,应用程序的进程仍然存在,并且可以快速恢复到之前的状态,而不需要重新初始化和加载 UI 界面。

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

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

相关文章

Jmeter基础(1) Mac下载安装启动

目录 Jmeter下载安装启动下载启动 Jmeter下载安装启动 注意⚠️:使用jmeter需要有java环境 下载 官网下载地址:https://jmeter.apache.org/ 会看到这里有两个版本,那么有什么区别么? Binaries是可执行版,直接下载解…

Python算法题集_图论(课程表)

Python算法题集_课程表 题207:课程表1. 示例说明2. 题目解析- 题意分解- 优化思路- 测量工具 3. 代码展开1) 标准求解【循环递归全算】2) 改进版一【循环递归缓存】3) 改进版二【循环递归缓存反向计算】4) 改进版三【迭代剥离计数器检测】 4. 最优算法5. 相关资源 本…

Spring整合Junit4和Junit5

1、整合的好处 好处1&#xff1a;不需要自己创建IOC容器对象了好处2&#xff1a;任何需要的bean都可以在测试类中直接享受自动装配 2、操作 整合junit4 ①加入依赖 <dependency><groupId>junit</groupId><artifactId>junit</artifactId><…

代码随想录算法训练营第二十三天补|669. 修剪二叉搜索树 ● 108.将有序数组转换为二叉搜索树 ● 538.把二叉搜索树转换为累加树

平衡树、二叉树、灵活应用中序遍历&#xff08;值大小有序&#xff09; 669. 修剪二叉搜索树 给你二叉搜索树的根节点 root &#xff0c;同时给定最小边界low 和最大边界 high。通过修剪二叉搜索树&#xff0c;使得所有节点的值在[low, high]中。修剪树 不应该 改变保留在树中…

Window部署SkyWalking

SkyWalking mysql的驱动依赖 选择下载版本 v9.4 现在后解压缩目录结构 一、修改config目录文件 application.yml 修改1&#xff1a; selector: ${SW_STORAGE:h2} 修改后&#xff1a; selector: ${SW_STORAGE:mysql} 修改2&#xff1a;使用mysql数据库 mysql: properti…

通俗易懂分析:Vite和Webpack的区别

1、对项目构建的理解 先从浏览器出发&#xff0c; 浏览器是由浏览器内核和JS引擎组成&#xff1b;浏览器内核编译解析html代码和css代码&#xff0c;js引擎编译解析JavaScript代码&#xff1b;所以从本质上&#xff0c;浏览器只能识别运行JavaScript、CSS、HTML代码。 而我们在…

敏捷开发最佳实践:领导力维度实践案例——走动式激励

在本节实践案例中&#xff0c;某财险公司信息技术部高级工程师分享了组织级数字化转型中的优秀敏捷领导力实践&#xff0c;不仅解决了产品上市周期长、响应市场变化慢的难题&#xff0c;还打破了部门墙、提升了客户满意度&#xff0c;该案例将为同类企业在组织层面进行有效敏捷…

Centos7配置静态IP详细步骤

使用Centos虚拟机测试时一到切换网段就头疼&#xff0c;总是会有ping不通网关、同段IP和外网的情况。下面出一个尽可能完整的排查思路和配置静态IP的过程。以下为配置nat模式后&#xff0c;出现以上情况的网络不通的排查思路&#xff0c;并配置win10vm8静态IP和centos7虚机nat模…

vue3路由切换过渡动画实现

<router-view v-slot"{ Component }"><transition name"fade" mode"out-in" appear><keep-alive><component :is"Component" /></keep-alive></transition> </router-view>/* 路由切换动画…

SQL字符集

目标:了解字符集的概念&#xff0c;掌握MySQL数据库存储数据的字符集逻辑以及设置方式 字符集概念 MySQL字符集关系 解决乱码问题 字符集设置原理 1、字符集概念 目标:了解字符集概念&#xff0c;掌握字符集存储和读取的实现原理 概念 字符集:charset或者character set&am…

(十二)【Jmeter】线程(Threads(Users))之setUp 线程组

简述 操作路径如下: 作用:在正式测试开始前执行预加载或预热操作,为测试做准备。配置:设置预加载或预热操作的采样器、循环次数等参数。使用场景:确保在正式测试开始前应用程序已经达到稳定状态,减少测试结果的偏差。优点:提供预加载或预热操作,确保测试的准确性。缺…

Centos开机网卡自启动失败

问题背景 每次都要手动启动在这里插入代码片 解决方案: 关闭 NetworkManager 服务 systemctl disable NetworkManager systemctl stop NetworkManager重启就会发现网卡已经可以自动启动了

2024幻兽帕鲁游戏服务器租用价格表_一年和1个月报价明细

游戏服务器租用多少钱一年&#xff1f;1个月游戏服务器费用多少&#xff1f;阿里云4核16G10M游戏服务器26元1个月、149元半年&#xff0c;腾讯云4核16G游戏服务器32元、312元一年&#xff0c;华为云26元&#xff0c;京东云主机也是26元起&#xff0c;游戏服务器配置从4核16G、4…

代码随想录算法刷题训练营day22

代码随想录算法刷题训练营day22&#xff1a;LeetCode(236)二叉树的最近公共祖先、LeetCode(235) 二叉搜索树的最近公共祖先、LeetCode(701)二叉搜索树中的插入操作、LeetCode(450)删除二叉搜索树中的节点 LeetCode(236)二叉树的最近公共祖先 题目 代码 /*** Definition for…

【鸿蒙 HarmonyOS 4.0】路由router

一、介绍 页面路由指在应用程序中实现不同页面之间的跳转和数据传递。HarmonyOS提供了Router模块&#xff0c;通过不同的url地址&#xff0c;可以方便地进行页面路由&#xff0c;轻松地访问不同的页面。 二、页面跳转 2.1、两种跳转模式&#xff1a; router.pushUrl()&…

vue2与vue3中父子组件传参的区别

本次主要针对vue中父子组件传参所进行讲解 一、vue2和vue3父传子区别 1.vue2的父传子 1).在父组件子标签中自定义一个属性 <sonPage :子组件接收到的类名"传输的数据">子组件</sonPage> 2).在子组件中peops属性中拿到自定属性 props: {子组件接收的…

Stable Diffusion算法、结构全流程概述

Stable Diffusion能力强、功能多、插件广&#xff0c;本文拟概述SD的全流程&#xff0c;方便梳理算法各结构的关系 1、stable diffusion训练用ddpm, 采样用ddim DDPM的推理采样步长和训练时的步长一样&#xff0c;导致采样步数过多&#xff0c;推理时间长。DDIM指出&#xff…

安卓游戏开发之音频技术优劣分析

一、引言 在安卓游戏开发中&#xff0c;音频处理技术扮演着至关重要的角色&#xff0c;它不仅能够增强游戏的沉浸感和玩家体验&#xff0c;还能通过声音效果传达关键的游戏信息。以下将对几种常见的安卓游戏音频处理技术进行优劣分析&#xff0c;并结合应用场景来阐述其特点。 …

docker镜像打包和解压

背景 工作记录 打包镜像 docker save -o 压缩包名称.tar 镜像名称:镜像版本 例如 docker save -o app-web.tar app-web:2.0解压镜像 这里解压上面打包的app-web的压缩包 docker load<压缩包名称.tar docker load<app-web.tar这样解压下来的实际就是app-web:2.0这个镜…

微服务-微服务API网关Spring-clould-gateway实战

1. 需求背景 在微服务架构中&#xff0c;通常一个系统会被拆分为多个微服务&#xff0c;面对这么多微服务客户端应该如何去调用呢&#xff1f; 如果根据每个微服务的地址发起调用&#xff0c;存在如下问题&#xff1a; 1.客户端多次请求不同的微服务&#xff0c;会增加客户端…