65%更小的APK和70%更少的内存:如何优化我的Android App的内存

news2024/11/24 7:53:16

65%更小的APK和70%更少的内存:如何优化我的Android App的内存

(Note: This is a translation of the provided title)

为什么应用程序内存很重要?

使用最少的内存的高效应用程序可以提升性能,节省设备资源并延长电池寿命。它们提供流畅的用户体验,并且在应用商店中更受欢迎。这样的应用程序与各种设备兼容。

跟踪内存的方法

我们可以采用以下任一方法来跟踪应用程序的内存:

1. ADB 命令

要在特定时刻获取应用程序的内存,请在终端中运行以下命令:

adb shell dumpsys meminfo appPackageName

注意:将 ‘appPackageName’ 替换为您要监视的应用程序的实际包名。

上面的示例截图显示该应用程序的内存使用量为 42MB。

优点
获取设备中任何应用程序的内存。
限制
无法像 Android Profiler 那样根据用户交互以图表形式监视内存变化。

2. Android Profiler

启动 Profiler 的步骤

View(在顶部窗格)-> Tool Windows -> Profiler -> 点击 “+” -> 选择设备和包

优点
Android Profiler 可以根据应用程序的使用情况跟踪运行时行为和内存消耗。
它提供了对应用程序内存的全面视图。
限制
只能对“可调试的应用程序”进行性能分析。

注意:请注意,本文档中不涉及内存分析。要获取更深入的信息,请参阅官方文档。

我们的应用程序在图像方面非常重要,并且我们已经注意到,在浏览了 47 张图片后,应用程序的内存使用量超过了 500MB(如上面的截图所示)。这将增加遇到内存溢出异常 (OOM) 的风险。我们意识到需要进行内存优化以提高用户体验,并采取了以下措施。让我们开始吧…

内存优化措施

1. 像素颜色格式更改

像素颜色格式:像素颜色格式,也称为像素格式,指定了图像中每个像素的颜色信息在内存中的存储方式。它定义了红色、绿色、蓝色和 alpha(透明度)组件的排列方式,影响着颜色质量和渲染性能。

在 Android 中,支持多种颜色格式。然而,让我们重点关注下面最常用的几种。

ARGB_8888(每像素32位)- 8 位用于 alpha(透明度),8 位用于红色,8 位用于绿色,8 位用于蓝色

RGB_565(每像素16位)- 5 位用于红色,6 位用于绿色,5 位用于蓝色,没有 alpha

如上图所示,RGB 565 和 ARGB 8888 之间的差异几乎不可察觉,但是在 RGB 565 中内存减少了约 50%。

我们使用 Glide 库进行图像渲染。默认情况下,Glide 使用 ARGB 8888 像素颜色格式进行图像加载。然而,Glide 提供了配置首选像素颜色格式的灵活性。

@GlideModule
class CustomGlideModule : AppGlideModule() {
    override fun applyOptions(context: Context, builder: GlideBuilder) {
        builder.setDefaultRequestOptions(RequestOptions().format(DecodeFormat.PREFER_RGB_565))
    }
}

如上所示,我们在应用程序级别上将默认颜色格式调整为RGB 565。此配置更改导致每个像素的内存消耗减少50%。对于依赖图像的项目,这个决策非常重要。

注意:RGB 565具有某些限制,例如轻微的颜色变化和不支持透明度。这可能会导致特定图像的颜色精度降低,因此选择应基于应用程序的特定要求而做出。

2. Glide DiskCacheStrategy 更改

DiskCacheStrategy主要确定图像在设备上的缓存方式。

先前,我们使用的是“DiskCacheStrategy.All”。但是,在进行一些研究后,我们意识到“DiskCacheStrategy.Resource”更符合我们的特定需求。

DiskCacheStrategy.ALL -> 缓存图像的所有版本。

DiskCacheStrategy.Resource-> Glide仅在磁盘上缓存所有转换(例如调整大小,裁剪)后的最终图像。当您想要缓存完全处理的图像而不是原始数据时,此策略是理想的。

官方文档中可以引用其他DiskCacheStrategies

例如,在WhatsApp等应用程序中,图像通常以压缩格式显示。但是,偶尔用户可能想要在其原始的高分辨率状态下共享这些图像。在这种情况下,DiskCacheStrategy.Resource将不适用。

因此,diskCacheStrategy的选择取决于应用程序的特定要求。

** 3. 修改offscreenPageLimit **

最初为了最小化延迟和防止空白屏幕,我们将offscreenPageLimit配置为3以用于ViewPager。我们的假设是ViewPager会缓存前一页,当前页和下一页。然而,经过更深入的调查,我们发现它实际上缓存了前三页,当前页和下三页,这导致总共存储了7个大型高清晰度图像。

基于这个分析,我们选择将offscreenPageLimit减少到1。这不仅减少了内存使用,还使应用程序在没有任何延迟问题的情况下平稳运行。

viewPager.offscreenPageLimit = 1

4. onViewRecycled时清除缓存

onViewRecycledRecyclerView.Adapter中的回调方法,在视图被回收时触发。它通常与Glide一起使用,以取消正在加载的图像,优化内存和网络使用。

override fun onViewRecycled(holder: ChildBingeHolder) {
        GlideApp.with(context).clear(yourView)
}

在适配器中回收视图时清除视图缓存有助于释放内存。

5. 指定图像大小

我们有一个64x64像素(小型)ImageView,但API提供的是512x512像素(大型)图像。为小占位符解码如此大的图像在内存使用和应用程序性能方面效率低下。

为了解决这个问题,我们指定了视图的宽度和高度,以确保正确缩放图像,而不是将超大的图像加载到内存中。

Glide.with(this)
        .load(IMAGE_URL)
        .override(targetWidth, targetHeight)
        .into(imageView)

使用override()可以通过指定所需的图像尺寸来大大减少内存消耗,这在处理大型图像或同时显示多个图像时特别有用。

6. 处理onTrimMemory

实现onTrimMemory(int)以根据系统约束逐步释放内存。这通过使您的进程更长时间地保持活动状态来改善系统响应性和用户体验。如果没有资源修剪,系统可能会杀死您的缓存进程,需要您的应用程序重新启动并在用户返回时恢复状态。

注意:以下内存级别处理是针对我们应用程序的特定要求进行定制的。我们正在根据需要自定义内存级别。内存级别文档

override fun onTrimMemory(level: Int) {
    //Memory Levels documentation : https://developer.android.com/reference/android/content/ComponentCallbacks2
    // TRIM_MEMORY_COMPLETE & TRIM_MEMORY_MODERATE are the levels which are called when the app is in background
    if (level == android.content.ComponentCallbacks2.TRIM_MEMORY_COMPLETE) {
        GlideApp.get(this).clearMemory()
    } else if (level == android.content.ComponentCallbacks2.TRIM_MEMORY_MODERATE) {
        GlideApp.with(this).onTrimMemory(TRIM_MEMORY_MODERATE)
    }
}

在实施上述步骤并进行一些微小的调整后,我们成功地实现了应用程序内存管理的显著改进。

在提供的屏幕截图中,我们可以观察到内存行为。它清楚地表明,内存保持不变,并且在不断滚动图像期间有效地管理任何未使用的内存。

结果:

如上表所示,内存使用从浏览47张图像时的515MB减少到浏览67张图像时的137MB(超过70%的减少)。这种改进使我们能够在不担心内存限制的情况下向应用程序添加更多图像。

结论

总之,我们优化应用程序的旅程展示了减少APK大小和优化内存的显着影响。这些努力不仅改善了用户体验,还为更高效的应用程序性能铺平了道路,使我们能够向客户交付更好,更快,更流畅的应用程序。

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

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

相关文章

学生台灯选什么光源好?适合学生的护眼台灯推荐

现在的台灯可以说是孩子必不可少的一个学习灯具了,几乎每家每户都会备着一台。不过台的好坏也有区别,相对而言,以前所用的白炽灯、日光灯、节能灯等等传统台灯已经是不适合孩子使用的了,目前而言最好的是LED灯。下面小编为大家推荐…

【消费战略】解读100个食品品牌|意面突起,“空刻”的品类心智占位!

空刻意面,一个开创意大利面速食化的新消费品牌,凭借着核心大单品意大利面,在过去短短的几年中,获得不俗的市场成绩和品牌影响力,占领了空刻意面的消费心智: 2019年,AIRMETER氢刻意面上线天猫旗舰…

急需一个可以短视频配音的手机App~

很多小伙伴视频拍摄得很好,但不想用自己的声音做解说旁白,怎么办?这时候就急需一个可以配音的手机App!今天给大家推荐一款一款专注于文字转语音的智能语音合成工具——悦音配音。声音堪比真人发声的配音服务平台,里面拥…

在 Windows 10/11 上恢复已删除文件的 9 种简单方法

本教程讨论永久丢失数据的原因以及在 Windows 10/11 上恢复已删除文件的不同方法: 数据是提供给系统的任何形式的信息。它可以是从密码到记事本文件的任何内容。数据是当今世界的关键要素,因为它使我们的生活变得轻松。 我们每天都变得越来越依赖数据&…

如何禁止别人调试自己的前端代码?

在前端开发中,无法完全禁止别人对自己的前端代码进行调试,因为前端代码在客户端执行,而客户端环境是可被用户访问和控制的。然而,可以采取一些措施来增加代码的安全性和复杂度,使得调试和代码分析变得更加困难。以下是…

橡胶软管在气密测试时如何保持管口的形状不变

在汽车整机或者零部件中,我们经常能看到各种各样的橡胶软管,主要负责导通各种冷却液、油等,是汽车正常工作不可分割的一部分。为了确保软管在使用前具有良好的密封性能,出厂前的气密性测试可以检测软管是否存在漏气或渗漏的问题&a…

新零售系统主要功能有哪些?新零售系统开发公司推荐

新零售系统是一套全面的数字化解决方案,旨在帮助实体零售店提升运营效率、优化用户体验并实现持续增长。以下是新零售系统的主要功能: l 用户画像:系统通过收集和分析顾客的行为、偏好、购买历史等数据,构建出完整的用户画像。这…

智加科技与东风柳汽达成深度合作 自动驾驶重卡计划2024年初量产交付

(2023年10月19日,苏州)全球领先的重卡自动驾驶技术公司智加科技与东风柳汽宣布,双方共同开发的自动驾驶重卡H7计划2024年初实现量产交付。未来,双方将携手推出安全可靠、高性价比、性能卓越的自动驾驶重卡产品&#xf…

Java编译多个目录下的文件

编译单个目录下的Java文件 javac -d <放置输出类文件的目录> <源文件的目录>/*.java 例如&#xff0c;在src/com/thb目录下有两个java文件&#xff1a; 执行编译命令javac -d D:\temp\outputdata src/com/thb/*.java可以编译这个目录下的两个java文件&#xff…

华为云HECS安装docker-compose

Docker Compose是一个用来定义和运行多个复杂应用的Docker编排工具。例如&#xff0c;一个使用Docker容器的微服务项目&#xff0c;通常由多个容器应用组成。那么部署时如何快速启动各个微服务呢&#xff0c;一个个手动启动&#xff1f;假如有上百个微服务呢&#xff0c;显然不…

python 打包 pyinstall

一、PyInstaller介绍 一个打包工具&#xff0c;可将Python代码打包成单个可执行文件&#xff0c;支持Windows、macOS和Linux等多个平台&#xff0c;可以将依赖包和资源文件一起打包。 二、PyInstaller安装及使用方法 1.PyInstaller安装 在终端执行&#xff1a; pip instal…

LongAdder为什么在高并发下保持良好性能?LongAdder源码详细分析

文章目录 一、LongAdder概述1、为什么用LongAdder2、LongAdder使用3、LongAdder继承关系图4、总述&#xff1a;LongAdder为什么这么快5、基本原理 二、Striped64源码分析1、Striped64重要概念2、Striped64常用变量或方法3、静态代码块初始化UNSAFE4、casBase方法5、casCellsBus…

新能源汽车展厅用哪些种类的显示屏比较好?

现在有越来越多的新能源汽车展厅开到了商场、购物中心当中。在新能源汽车展厅中&#xff0c;显示屏已经成为不可或缺的设备设施&#xff0c;可以用来展现产品介绍、优惠信息、文化宣传等。那么新能源汽车展厅的显示大屏用什么屏比较好呢&#xff1f; LED大屏幕&#xff1a;LED显…

【FPGA】IIC协议主机接口的设计与实现详解

一、认识IIC IIC&#xff08;I2C&#xff09;协议是一种串行通信协议&#xff0c;用于连接微控制器和外围设备。IIC协议只需要两根信号线&#xff08;时钟线SCL和数据线SDA&#xff09;就能完成设备之间的通信&#xff1b;支持多主机和多从机通信&#xff0c;通过设备地址区分不…

医院智能电力系统解决方案

摘要&#xff1a;智能电力系统主要体现在“智能”&#xff0c;在医院中智能电力系统主要以数字电力系统为主&#xff0c;它主要表现为信息化、自动化。通过对数据的采集分析&#xff0c;以及反馈传输运行。其中医院智能电力系统优点在于&#xff0c;(1)通过医院的生产数据&…

移动端点击任意下拉框或复选框文本框都会出现绿色背景?

css自带的样式实在太恶心了&#xff0c;下图任意点击下拉框&#xff0c;复选框都会出现绿色背景。 解决方式如下&#xff1a; * {-webkit-tap-highlight-color: rgba(0,0,0,0); }

【数据结构与算法】JavaScript实现队列结构(Queue)

文章目录 JavaScript实现队列结构&#xff08;Queue&#xff09;一、队列简介二、封装队列类2.1.代码实现2.2.队列的应用 三、优先队列3.1.优先级队列的实现3.2.注意点 JavaScript实现队列结构&#xff08;Queue&#xff09; 一、队列简介 队列是是一种受限的线性表&#xff…

ROS1 常用命令行工具

1. 启动ros 主节点 roscore roscore运行成功如图&#xff1a; 1.1 rosrun 启动服务节点 例子&#xff1a;启动一个小乌龟节点 rosrun turtlesim turtlesim_node运行结果如图&#xff1a; 1.2 启动键盘控制 打开新的命令窗口&#xff0c;启动turtle_teleop_key 节点 rosr…

Servlet中乱码解决

总决式:解决乱码.不写中文 创建个Javaweb项目,演示并解决各种乱码 直接next pom.xml里自动引入了servletapi 目录结构 一般创建好项目先设置下maven与Encoding 建个Servlet测试 启动并访问 无论控制台输出用GBK还是UTF8 都是乱码 此时需要修改Tomcat/conf/logging.propertie…

Cesium 实战 - 调整色调、对比度等参数,加载渲染暗黑底图

Cesium 实战 - 调整色调、对比度等参数&#xff0c;加载渲染暗黑底图 渲染暗黑底图核心代码完整代码&#xff1a;在线示例 本文包括渲染暗黑底图核心代码、完整代码以及在线示例。 渲染暗黑底图核心代码 这里放上核心代码&#xff1a; /*** todo 开启暗黑底图* param {Object}…