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 heapsizenative 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 频繁创建短生命周期对象

        在循环或频繁调用的方法中创建大量短生命周期的对象,如字符串拼接、对象频繁创建等。

        在自定义控件的onMeasureonLayoutonDraw等方法中创建对象,由于这些方法会频繁调用,导致对象频繁创建和回收。

解决方案

  • 避免在循环或频繁调用的方法中创建对象。
  • 使用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 资源文件未关闭

        在处理文件、数据库连接等资源时,如果未正确关闭这些资源,也可能导致内存泄露。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【Python 数据结构 5.栈】

目录 一、栈的基本概念 1.栈的概念 2.入栈 入栈的步骤 3.出栈 出栈的步骤 4.获取栈顶元素 获取栈顶元素的步骤 二、 Python中的栈 顺序表实现 链表实现 三、栈的实战 1.LCR 123. 图书整理 I 思路与算法 2.LCR 027. 回文链表 思路与算法 3.1614. 括号的最大嵌套深度 思路与算法 …

C++基础算法:模拟

文章目录 1.[P1067 [NOIP 2009 普及组\] 多项式输出 - 洛谷](https://www.luogu.com.cn/problem/P1067)题目解析算法解析代码实现 2.[P5731 【深基5.习6】蛇形方阵 - 洛谷](https://www.luogu.com.cn/problem/P5731)题目解析算法原理代码实现 3.[P1098 [NOIP 2007 提高组\] 字符…

关于对机器中的人工智能进行基准测试

大家读完觉得有帮助记得及时关注和点赞!!! 抽象 最近的基准研究声称,AI 在各种认知任务上的表现已经接近甚至超过人类的“水平”。然而,本立场文件认为,当前的 AI 评估范式不足以评估类似人类的认知能力。我…

c++ 内存管理系统之智能指针

1.c内存管理 1.代码区 也称Text Segment,存放可执行程序的机器码。 2 数据区: 存放已初始化的全局和静态变量, 常量数据(如字符串常量)。 存放未初始化的全局和静态变量 无疑解释静态变量的来源: 局…

Unity中的Destroy和DestroyImmediate的区别是什么?

在 Unity 中,Destroy 和 DestroyImmediate 都是用于销毁游戏对象(GameObject)、组件(Component)或资源的方法。在大多数情况下,建议优先使用 Destroy 方法,只有在确实需要立即销毁对象时才使用 …

Microk8s Ingress实现七层负载均衡

Microk8s Ingress是什么 Ingress是k8s的一种资源对象,用于管理外部对集群内服务的访问, 它通过提供一个统一的入口点,将外部流量路由到集群内部的不同服务。 Microk8s Ingress用于解决什么问题 k8s集群中服务默认只能在集群内访问。 如果需要从外部访…

DeepSpeek服务器繁忙?这几种替代方案帮你流畅使用!(附本地部署教程)

作者:后端小肥肠 目录 1. 前言 2. 解决方案 2.1. 纳米AI搜索(第三方平台) 2.2. Github(第三方平台) 2.3. 硅基流动(第三方API) 3. 本地部署详细步骤 3.1. 运行配置需求 3.2. 部署教程 4…

【大厂AI实践】美团:美团智能客服核心技术与实践

【大厂AI实践】美团:美团智能客服核心技术与实践 🌟 嗨,你好,我是 青松 ! 🌈 自小刺头深草里,而今渐觉出蓬蒿。 NLP Github 项目推荐: 【AI 藏经阁】:https://gitee.com…

科技查新有不通过的情况吗?为什么?

1. 科技查新有不通过的情况吗?为什么? 有。科技查新“不通过”(即查新报告显示技术缺乏新颖性或存在侵权风险)的情况并不罕见,主要原因包括: (1)技术缺乏创新性 重复开发&#xff…

批量提取 Word 文档中的页面

如何将 Word 文档中的页面提取出来形成一个新的文档呢?比如将 Word 文档中的第一页提取出来、将 Word 文档中的最后一页提取出来、再或者将 Word 文档中的中间几页提取出来等等。人工的处理肯定非常的麻烦,需要新建 Word 文档,然后将内容复制…

Spring统一格式返回

目录 一:统一结果返回 1:统一结果返回写法 2:String类型报错问题 解决方法 二:统一异常返回 统一异常返回写法 三:总结 同志们,今天咱来讲一讲统一格式返回啊,也是好久没有讲过统一格式返…

(十 八)趣学设计模式 之 观察者模式!

目录 一、 啥是观察者模式?二、 为什么要用观察者模式?三、 观察者模式的实现方式四、 观察者模式的优缺点五、 观察者模式的应用场景六、 总结 🌟我的其他文章也讲解的比较有趣😁,如果喜欢博主的讲解方式,…

Linux虚拟机网络配置-桥接网络配置

简介 本文档旨在指导用户如何在虚拟环境中配置Linux系统的桥接网络,以实现虚拟机与物理主机以及外部网络的直接通信。桥接网络允许虚拟机如同一台独立的物理机一样直接连接到物理网络,从而可以被分配一个独立的IP地址,并能够与网络中的其他设…

视频教育网站开源系统的部署安装 (roncoo-education)服务器为ubuntu22.04.05

一、说明 前端技术体系:Vue3 Nuxt3 Vite5 Vue-Router Element-Plus Pinia Axios 后端技术体系:Spring Cloud Alibaba2021 MySQL8 Nacos Seata Mybatis Druid redis 后端系统:roncoo-education(核心框架:S…

线程相关八股

1. 线程和进程的区别? 进程:进程可以简单理解为进行一个程序,比如说我们打开一个浏览器,打开一个文本,这就是开启了一个进程,一个进程想要在计算机中运行,需要将程序交给CPU,将数据…

Python 绘制迷宫游戏,自带最优解路线

1、需要安装pygame 2、上下左右移动,空格实现物体所在位置到终点的路线,会有虚线绘制。 import pygame import random import math# 迷宫单元格类 class Cell:def __init__(self, x, y):self.x xself.y yself.walls {top: True, right: True, botto…

【音视频】VLC播放器

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 一、vlc是什么? VLC Media Player(简称VLC)是一款免费、开源、跨平台的多媒体播放器,由非营利组织VideoLAN开发,最…

vue2+ele-ui实践

前言:真理先于实践,实践发现真理,再实践检验真理 环境:vue2 & element-ui 正片: Select 选择器 简称 下拉框 下拉框完整的使用循环 下拉框 → 点击下拉框 → 展示数据 → 选择数据 → 下拉框显示数据 核心具有…

刷题日记——部分二分算法题目分享

前言 咱们紧跟上一期结合时间复杂度浅谈二分法的好处, 并分享部分二分题目(将持续更新题目,绝对值你一个收藏)-CSDN博客 笔者接着分享一些刷过的关于二分算法的题目. 第一题 1283. 使结果不超过阈值的最小除数 - 力扣(LeetCode) 这道题就是典型的二…

excel 斜向拆分单元格

右键-合并单元格 右键-设置单元格格式-边框 在设置好分割线后,你可以开始输入文字。 需要注意的是,文字并不会自动分成上下两行。 为了达到你期望的效果,你可以通过 同过左对齐、上对齐 空格键或使用【AltEnter】组合键来调整单元格中内容的…