当前位置: 首页 > article >正文

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 资源文件未关闭

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


http://www.kler.cn/a/563032.html

相关文章:

  • PCL源码分析:曲面法向量采样
  • RK3568平台开发系列讲解(内核篇)Linux 内核启动流程
  • 观成科技:海莲花“PerfSpyRAT”木马加密通信分析
  • 微服务架构与传统的单体架构有什么区别?微服务架构(Spring Cloud + Maven)强在哪?
  • LeetCode 1472.设计浏览器历史记录:一个数组完成模拟,单次操作均O(1)
  • css实现左右切换平滑效果
  • 数字人AIGC实训室:以AI技术赋能数字化教育
  • python基础学习day01
  • 高效能计算与高速数据传输的完美结合:飞腾D2000处理器与复旦微双FPGA集成主板
  • 数据库二三事(8)
  • 数组的使用
  • HTTPS 与 HTTP 的区别在哪?
  • DeepSeek开源周Day1:FlashMLA引爆AI推理性能革命!
  • PyTorch 源码学习:GPU 内存管理之它山之石——TensorFlow BFC 算法
  • python爬虫学习第十一篇爬取指定类型数据
  • Qt Creator + CMake 构建教程
  • QT和有道词典有冲突,导致内存溢出,闪退。
  • LeetCode详解之如何一步步优化到最佳解法:14. 最长公共前缀
  • JavaScript 系列之:Ajax、Promise、Axios
  • 【人工智能】数据挖掘与应用题库(101-200)