Android内存优化指南:从数据结构到5R法则的全面策略
目录
一、APP 内存限制
二、内存的三大问题
2.1、内存抖动(Memory Churn)
2.1.1 频繁创建短生命周期对象
2.1.2 系统API或第三方库的不合理使用
2.1.3 Handler使用不当
2.2、内存泄漏(Memory Leak)
2.2.1 静态变量持有Activity或Context引用
2.2.2 未取消的回调或监听器
2.2.3 非静态内部类持有外部类引用
2.2.4 Timer或Handler未正确取消
2.2.5 Bitmap未及时回收
2.2.6 资源文件未关闭
2.2.7 WebView
2.3、内存溢出(OutOfMemoryError)
2.3.1 为对象分配内存时达到进程的内存上限
2.3.2 没有足够大小的连续地址空间
2.3.3 创建线程失败
2.3.4 内存泄漏积累
2.3.5 集合类对象未及时清理
三、内存问题解决方案
3.1 选择合适的数据结构
3.2 避免使用枚举
3.3 谨慎使用多进程
3.4 谨慎使用 Large Head
3.5 使用NDK
四、 图片优化
4.1 如何对图片进行缓存?
4.2 计算图片占用内存的大小
4.3 如何计算图片占用内存的大小?
4.4 图片内存体积优化总结
五、内存优化5R法则
相关推荐
一、APP 内存限制
Android 给每个 App 分配一个 VM ,让App运行在 dalvik 上,这样即使 App 崩溃也不会影响到系统。系统给 VM 分配了一定的内存大小,App 可以申请使用的内存大小不能超过此硬性逻辑限制,就算物理内存富余,如果应用超出 VM 最大内存,就会出现内存溢出 crash。
由程序控制操作的内存空间在 heap 上,分 java heapsize 和 native heapsize。
Java申请的内存在 vm heap 上,所以如果 java 申请的内存大小超过 VM 的逻辑内存限制,就会出现内存溢出的异常。(如:-Xmx4096)
native 层内存申请不受其限制,native 层受 native process 对内存大小的限制。
Android 虚拟机申请内存最大内存是有限制的,不同设备申请的最大内存是不一样的。
二、内存的三大问题
1、内存抖动:内存波动图形呈 锯齿张、GC导致卡顿。
2、内存泄漏:在当前应用周期内不再使用的对象被GC Roots引用,导致不能回收,使实际可使用内存变小。
3、内存溢出:即OOM,OOM时会导致程序异常。Android设备出厂以后,虚拟机对单个应用的最大内存分配就确定下来了,超出这个值就会OOM。
2.1、内存抖动(Memory Churn)
内存抖动是指内存频繁分配和回收,导致内存曲线呈锯齿状波动,可能导致应用页面卡顿或响应缓慢。常见的内存抖动场景及解决方案:
2.1.1 频繁创建短生命周期对象
在循环或频繁调用的方法中创建大量短生命周期的对象,如字符串拼接、对象频繁创建等。
在自定义控件的onMeasure
、onLayout
、onDraw
等方法中创建对象,由于这些方法会频繁调用,导致对象频繁创建和回收。
解决方案:
- 避免在循环或频繁调用的方法中创建对象。
- 使用StringBuilder等高效字符串拼接方式替代加号拼接。
- 在自定义控件的绘制方法中,尽量复用对象,避免频繁创建。
- 对于需要频繁创建和销毁的对象,可以考虑使用对象池来复用对象。对象池能够减少对象的创建和销毁次数,从而降低内存抖动的发生概率。
2.1.2 系统API或第三方库的不合理使用
调用系统API或第三方库时,没有合理使用其提供的对象复用机制,导致大量对象被创建。
解决方案:
- 深入了解系统API和第三方库的工作原理,合理使用其提供的对象复用机制。
- 避免不必要的对象创建,如使用
Message.obtain()
方法获取Message对象,而不是直接创建新的Message对象。
2.1.3 Handler使用不当
Handler发送大量消息,且消息处理不及时,导致消息对象堆积。
解决方案:
- 在Handler中处理消息时,确保及时处理并释放消息对象。
- 对于延时消息,要确保在Activity或View生命周期结束前取消未处理的消息。
- 队列优化=>重复消息过滤。
- 队列优化=>互斥消息取消。
- 复用消息,使用
Message.obtain()
方法获取Message对象。 - 使用消息空闲ldleHandle
2.2、内存泄漏(Memory Leak)
内存泄漏是指长生命周期的对象持有短生命周期对象的引用,应用程序中的对象在不再需要时仍然被引用,导致垃圾回收器(Garbage Collector,GC)无法回收这些对象所占用的内存。内存泄漏会导致可用内存逐渐减少,最终可能导致应用程序崩溃(OOM)或系统变得非常缓慢。常见的内存泄露场景及解决方案:
2.2.1 静态变量持有Activity或Context引用
在静态变量中持有Activity或Context的强引用,当Activity或Context不再需要时,由于静态变量的生命周期与应用程序相同,导致这些对象无法被回收。
解决方案:
- 避免在静态变量中持有Activity或Context的强引用。
- 如果确实需要持有Context,考虑使用Application Context或弱引用(WeakReference)。
2.2.2 未取消的回调或监听器
在Activity或Fragment中注册回调或监听器,但未在适当的生命周期方法中取消注册,导致Activity或Fragment被销毁后,回调或监听器仍持有其引用。
解决方案:
- 在Activity或Fragment的onDestroy或onDetach方法中取消所有回调和监听器注册。
- 使用View的观察者模式时,确保在View不再需要时解除观察。
2.2.3 非静态内部类持有外部类引用
非静态内部类默认持有其外部类的引用,如果非静态内部类被长期持有(如作为静态变量的成员),则外部类也无法被回收。
解决方案:
- 将内部类声明为静态内部类,并通过构造方法传递必要的Context或其他引用。
- 如果内部类需要访问外部类的成员,考虑使用弱引用持有外部类的引用。
2.2.4 Timer或Handler未正确取消
使用Timer或Handler时,如果未正确取消定时任务或消息,当Activity或Fragment销毁后,这些定时任务或消息仍可能持有其引用。
解决方案:
- 在Activity或Fragment的onDestroy或onDetach方法中取消所有Timer任务。
- 对于Handler,确保在Activity或View生命周期结束前处理完所有消息,并调用handler.removeCallbacksAndMessages(null)来取消所有回调和消息。
2.2.5 Bitmap未及时回收
在加载大图片或处理图片时,如果未及时回收Bitmap对象,可能导致内存泄露。
解决方案:
- 在不再需要Bitmap时,及时调用bitmap.recycle()方法回收Bitmap。
- 使用图片加载库(如Glide、Picasso)时,这些库通常会自动管理Bitmap的回收,但仍需注意避免在Activity或Fragment销毁后继续加载图片。
2.2.6 资源文件未关闭
在处理文件、数据库连接等资源时,如果未正确关闭这些资源,也可能导致内存泄露。
相关文章:
Android内存优化指南:从数据结构到5R法则的全面策略
目录 一、APP 内存限制 二、内存的三大问题 2.1、内存抖动(Memory Churn) 2.1.1 频繁创建短生命周期对象 2.1.2 系统API或第三方库的不合理使用 2.1.3 Handler使用不当 2.2、内存泄漏(Memory Leak) 2.2.1 静态变量持有Activity或Context引用 2.2.2 未取消的回调或…...

机器学习:线性回归,梯度下降,多元线性回归
线性回归模型 (Linear Regression Model) 梯度下降算法 (Gradient Descent Algorithm) 的数学公式 多元线性回归(Multiple Linear Regression)...
Linux上用C++和GCC开发程序实现两个不同MySQL实例下单个Schema稳定高效的数据迁移到其它MySQL实例
设计一个在Linux上运行的GCC C程序,同时连接三个不同的MySQL实例,其中两个实例中分别有两个Schema的表结构分别与第三实例中两个Schema个结构完全相同,同时复制两个实例中两个Schema里的所有表的数据到第三个实例中两个Schema里,使…...

RabbitMQ系列(一)架构解析
RabbitMQ 架构解析 RabbitMQ 是一个基于 AMQP 协议的开源消息中间件,其核心架构通过多组件协作实现高效、可靠的消息传递。以下是其核心组件与协作流程的详细说明: 一、核心组件与功能 Broker(消息代理服务器) RabbitMQ 服务端核…...
XSL 语言:XML 样式表的语言基础与应用
XSL 语言:XML 样式表的语言基础与应用 引言 XSL(Extensible Stylesheet Language)是一种专门用于XML文档样式的语言,它允许用户定义XML文档的格式、布局和外观。XSL是XML技术家族中的重要组成部分,与XML和XPATH等语言共同构成了处理和格式化XML文档的强大工具集。本文将…...
【计算机网络】常见tcp/udp对应的应用层协议,端口
TCP 和 UDP 对应的常见应用层协议 📌 基于 TCP 的应用层协议 协议全称用途默认端口HTTPHyperText Transfer Protocol超文本传输协议80HTTPSHTTP Secure加密的超文本传输协议443FTPFile Transfer Protocol文件传输协议(20 传输数据,21 控制连…...

ExpMoveFreeHandles函数分析和备用空闲表的关系
第一部分:ExpMoveFreeHandles和备用空闲表的关系 ULONG ExpMoveFreeHandles ( IN PHANDLE_TABLE HandleTable ) { ULONG OldValue, NewValue; ULONG Index, OldIndex, NewIndex, FreeSize; PHANDLE_TABLE_ENTRY Entry, FirstEntry; EXHAND…...

微服务学习(1):RabbitMQ的安装与简单应用
目录 RabbitMQ是什么 为什么要使用RabbitMQ RabbitMQ的安装 RabbitMQ架构及其对应概念 队列的主要作用 交换机的主要作用 RabbitMQ的应用 通过控制面板操作(实现收发消息) RabbitMQ是什么 RabbitMQ是一个开源的消息队列软件(消息代理…...

基于javaweb的SSM+Maven幼儿园管理系统设计和实现(源码+文档+部署讲解)
技术范围:SpringBoot、Vue、SSM、HLMT、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、小程序、安卓app、大数据、物联网、机器学习等设计与开发。 主要内容:免费功能设计、开题报告、任务书、中期检查PPT、系统功能实现、代码编写、论文编写和辅导、论…...
企业级本地知识库部署指南(Windows优化版)
一、环境准备 1. 系统优化 # 启用WSL2(需Windows 10 2004或Windows 11) dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart dism.exe /online /enable-feature /featurename:VirtualMachinePlatform …...

5. Nginx 负载均衡配置案例(附有详细截图说明++)
5. Nginx 负载均衡配置案例(附有详细截图说明) 文章目录 5. Nginx 负载均衡配置案例(附有详细截图说明)1. Nginx 负载均衡 配置实例3. 注意事项和避免的坑4. 文档: Nginx 的 upstream 配置技巧5. 最后: 1. Nginx 负载均衡 配置实例 需求说明/图解 windows 浏览器输…...

Redis---缓存穿透,雪崩,击穿
文章目录 缓存穿透什么是缓存穿透?缓存穿透情况的处理流程是怎样的?缓存穿透的解决办法缓存无效 key布隆过滤器 缓存雪崩什么是缓存雪崩?缓存雪崩的解决办法 缓存击穿什么是缓存击穿?缓存击穿的解决办法 区别对比 在如今的开发中&…...

计算机毕业设计SpringBoot+Vue.js人口老龄化社区服务与管理平台 (源码+文档+PPT+讲解)
温馨提示:文末有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:文末有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:文末有 CSDN 平台官方提供的学长联系方式的名片! 作者简介:Java领…...

【异地访问本地DeepSeek】Flask+内网穿透,轻松实现本地DeepSeek的远程访问
写在前面:本博客仅作记录学习之用,部分图片来自网络,如需引用请注明出处,同时如有侵犯您的权益,请联系删除! 文章目录 前言依赖Flask构建本地网页访问LM Studio 开启网址访问DeepSeek 调用模板Flask 访问本…...

Nacos + Dubbo3 实现微服务的Rpc调用
文章目录 概念整理基本概念概念助记前提RPC与HTTP类比RPC接口类的一些理解 实例代码主体结构父项目公共接口项目提供者项目项目结构POM文件实现配置文件实现公共接口实现程序入口配置启动项目检查是否可以注入到Nacos 消费者项目项目结构POM文件实现配置文件实现注册RPC服务类实…...

散户如何实现自动化交易下单——篇1:体系介绍与获取同花顺资金账户和持仓信息
一、为什么要实现自动化交易 在瞬息万变的金融市场中,越来越多的散户投资者开始尝试构建自己的交易策略:有人通过技术指标捕捉趋势突破,有人利用基本面分析挖掘低估标的,还有人设计出复杂的网格交易或均值回归模型。然而&a…...

基于Electron的应用程序安全测试基础 — 提取和分析.asar文件的案例研究
目录: 4.4. 案例研究 4.4.2. 情况描述 4.4.3. 信息收集 4.4.3.2. 检查隐藏目录(点目录)的可能性 4.4.3.3. 使用 DB Browser for SQLite 打开 .db 文件 4.4.3.4. 寻找加密算法 4.4.3.5. 找到加密算法 4.4.3.6. 理解加密流程 4.4.3.7. 找到“Ke…...
vue中computed方法使用;computed返回函数
文章目录 1.正常使用computed2.使用computed返回可传参的函数 1.正常使用computed 一般我们使用computed返回一个变量字段,这个字段会根据具体的某个变量计算得到 例如 <div>{{num}}--{{num10}}</div>let num ref(1) let num10 computed(()>{ret…...
大语言模型的评测
大语言模型评测是评估这些模型在各种任务和场景下的性能和能力的过程。 能力 1. 基准测试(Benchmarking) GLUE(General Language Understanding Evaluation):包含多个自然语言处理任务,如文本分类、情感分…...

【Vue3】浅谈setup语法糖
Vue3 的 setup 语法糖是通过 <script setup> 标签启用的特性,它是对 Composition API 的进一步封装,旨在简化组件的声明式写法,同时保留 Composition API 的逻辑组织能力。以下是其核心概念和原理分析: 一、<script setu…...

大数据学习栈记——Neo4j的安装与使用
本文介绍图数据库Neofj的安装与使用,操作系统:Ubuntu24.04,Neofj版本:2025.04.0。 Apt安装 Neofj可以进行官网安装:Neo4j Deployment Center - Graph Database & Analytics 我这里安装是添加软件源的方法 最新版…...
Android Wi-Fi 连接失败日志分析
1. Android wifi 关键日志总结 (1) Wi-Fi 断开 (CTRL-EVENT-DISCONNECTED reason3) 日志相关部分: 06-05 10:48:40.987 943 943 I wpa_supplicant: wlan0: CTRL-EVENT-DISCONNECTED bssid44:9b:c1:57:a8:90 reason3 locally_generated1解析: CTR…...

大话软工笔记—需求分析概述
需求分析,就是要对需求调研收集到的资料信息逐个地进行拆分、研究,从大量的不确定“需求”中确定出哪些需求最终要转换为确定的“功能需求”。 需求分析的作用非常重要,后续设计的依据主要来自于需求分析的成果,包括: 项目的目的…...

云启出海,智联未来|阿里云网络「企业出海」系列客户沙龙上海站圆满落地
借阿里云中企出海大会的东风,以**「云启出海,智联未来|打造安全可靠的出海云网络引擎」为主题的阿里云企业出海客户沙龙云网络&安全专场于5.28日下午在上海顺利举办,现场吸引了来自携程、小红书、米哈游、哔哩哔哩、波克城市、…...

Vue3 + Element Plus + TypeScript中el-transfer穿梭框组件使用详解及示例
使用详解 Element Plus 的 el-transfer 组件是一个强大的穿梭框组件,常用于在两个集合之间进行数据转移,如权限分配、数据选择等场景。下面我将详细介绍其用法并提供一个完整示例。 核心特性与用法 基本属性 v-model:绑定右侧列表的值&…...
深入浅出:JavaScript 中的 `window.crypto.getRandomValues()` 方法
深入浅出:JavaScript 中的 window.crypto.getRandomValues() 方法 在现代 Web 开发中,随机数的生成看似简单,却隐藏着许多玄机。无论是生成密码、加密密钥,还是创建安全令牌,随机数的质量直接关系到系统的安全性。Jav…...

全球首个30米分辨率湿地数据集(2000—2022)
数据简介 今天我们分享的数据是全球30米分辨率湿地数据集,包含8种湿地亚类,该数据以0.5X0.5的瓦片存储,我们整理了所有属于中国的瓦片名称与其对应省份,方便大家研究使用。 该数据集作为全球首个30米分辨率、覆盖2000–2022年时间…...

Mac软件卸载指南,简单易懂!
刚和Adobe分手,它却总在Library里给你写"回忆录"?卸载的Final Cut Pro像电子幽灵般阴魂不散?总是会有残留文件,别慌!这份Mac软件卸载指南,将用最硬核的方式教你"数字分手术"࿰…...
VTK如何让部分单位不可见
最近遇到一个需求,需要让一个vtkDataSet中的部分单元不可见,查阅了一些资料大概有以下几种方式 1.通过颜色映射表来进行,是最正规的做法 vtkNew<vtkLookupTable> lut; //值为0不显示,主要是最后一个参数,透明度…...
全面解析各类VPN技术:GRE、IPsec、L2TP、SSL与MPLS VPN对比
目录 引言 VPN技术概述 GRE VPN 3.1 GRE封装结构 3.2 GRE的应用场景 GRE over IPsec 4.1 GRE over IPsec封装结构 4.2 为什么使用GRE over IPsec? IPsec VPN 5.1 IPsec传输模式(Transport Mode) 5.2 IPsec隧道模式(Tunne…...