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

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

目录

内存优化

在 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 关键字里加载。

java 复制代码
static {
	System.loadLibrary("so文件")
}

参考文章

1、Android 应用资源概述

7、使用插件化。

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

代码混淆

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

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

groovy 复制代码
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 所消耗的时间,如下:

shell 复制代码
 E:\Projects\StepDemo> adb shell am start -W com.binyouwei.demo/com.binyouwei.demo.MainActivity
 
Starting: 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 界面。

相关推荐
魔道不误砍柴功几秒前
Java 中如何巧妙应用 Function 让方法复用性更强
java·开发语言·python
NiNg_1_234几秒前
SpringBoot整合SpringSecurity实现密码加密解密、登录认证退出功能
java·spring boot·后端
闲晨3 分钟前
C++ 继承:代码传承的魔法棒,开启奇幻编程之旅
java·c语言·开发语言·c++·经验分享
_.Switch25 分钟前
高级Python自动化运维:容器安全与网络策略的深度解析
运维·网络·python·安全·自动化·devops
qq_2546744127 分钟前
工作流初始错误 泛微提交流程提示_泛微协同办公平台E-cology8.0版本后台维护手册(11)–系统参数设置
网络
JokerSZ.30 分钟前
【基于LSM的ELF文件安全模块设计】参考
运维·网络·安全
测开小菜鸟2 小时前
使用python向钉钉群聊发送消息
java·python·钉钉
数据猎手小k2 小时前
AndroidLab:一个系统化的Android代理框架,包含操作环境和可复现的基准测试,支持大型语言模型和多模态模型。
android·人工智能·机器学习·语言模型
P.H. Infinity3 小时前
【RabbitMQ】04-发送者可靠性
java·rabbitmq·java-rabbitmq