`

(三)如何避免OOM总结

 
阅读更多

前面介绍了一些基础的内存管理机制以及OOM的基础知识,那么在实践操作当中,有哪些指导性的规则可以参考呢?归纳下来,可以从四个方面着手,首先是减小对象的内存占用,其次是内存对象的重复利用,然后是避免对象的内存泄露,最后是内存使用策略优化。

减小对象的内存占用

避免OOM的第一步就是要尽量减少新分配出来的对象占用内存的大小,尽量使用更加轻量的对象。

1)使用更加轻量的数据结构

例如,我们可以考虑使用ArrayMap/SparseArray而不是HashMap等传统数据结构。图8演示了HashMap的简要工作原理,相比起Android专门为移动操作系统编写的ArrayMap容器,在大多数情况下,都显示效率低下,更占内存。通常的HashMap的实现方式更加消耗内存,因为它需要一个额外的实例对象来记录Mapping操作。另外,SparseArray更加高效,在于他们避免了对key与value的自动装箱(autoboxing),并且避免了装箱后的解箱。

 

图8  HashMap简要工作原理

关于更多ArrayMap/SparseArray的讨论,请参考《 Android性能优化典范(三)》的前三个段落。

2)避免在Android里面使用Enum

Android官方培训课程提到过“Enums often require more than twice as much memory as static constants. You should strictly avoid using enums on Android.”,具体原理请参考《Android性能优化典范(三)》,所以请避免在Android里面使用到枚举。

3)减小Bitmap对象的内存占用

Bitmap是一个极容易消耗内存的大胖子,减小创建出来的Bitmap的内存占用可谓是重中之重,通常来说有以下2个措施:

 

  • inSampleSize:缩放比例,在把图片载入内存之前,我们需要先计算出一个合适的缩放比例,避免不必要的大图载入。
  • decode format:解码格式,选择ARGB_8888/RBG_565/ARGB_4444/ALPHA_8,存在很大差异。

 

4)使用更小的图片

在涉及给到资源图片时,我们需要特别留意这张图片是否存在可以压缩的空间,是否可以使用更小的图片。尽量使用更小的图片不仅可以减少内存的使用,还能避免出现大量的InflationException。假设有一张很大的图片被XML文件直接引用,很有可能在初始化视图时会因为内存不足而发生InflationException,这个问题的根本原因其实是发生了OOM。

内存对象的重复利用

大多数对象的复用,最终实施的方案都是利用对象池技术,要么是在编写代码时显式地在程序里创建对象池,然后处理好复用的实现逻辑。要么就是利用系统框架既有的某些复用特性,减少对象的重复创建,从而降低内存的分配与回收(如图9所示)。

 

图9  对象池技术

在Android上面最常用的一个缓存算法是LRU(Least Recently Use),简要操作原理如图10所示。

 

图10  LRU简要操作原理

1)复用系统自带的资源

Android系统本身内置了很多的资源,比如字符串、颜色、图片、动画、样式以及简单布局等,这些资源都可以在应用程序中直接引用。这样做不仅能减少应用程序的自身负重,减小APK的大小,还可以在一定程度上减少内存的开销,复用性更好。但是也有必要留意Android系统的版本差异性,对那些不同系统版本上表现存在很大差异、不符合需求的情况,还是需要应用程序自身内置进去。

2)注意在ListView/GridView等出现大量重复子组件的视图里对ConvertView的复用,如图11所示。

 

图11

3)Bitmap对象的复用

在ListView与GridView等显示大量图片的控件里,需要使用LRU的机制来缓存处理好的Bitmap,如图12所示。

 

图12

 

  • 利用inBitmap的高级特性提高Android系统在Bitmap分配与释放执行效率(注:3.0以及4.4以后存在一些使用限制上的差异)。使用inBitmap属性可以告知Bitmap解码器去尝试使用已经存在的内存区域,新解码的Bitmap会尝试去使用之前那张Bitmap在Heap中所占据的pixel data内存区域,而不是去问内存重新申请一块区域来存放Bitmap。利用这种特性,即使是上千张的图片,也只会仅仅只需要占用屏幕所能够显示的图片数量的内存大小,如图13所示。

 

 

图13  利用inBitmap的高级特性提高Android在Bitmap分配与释放执行效率

使用inBitmap需要注意几个限制条件:

 

  • 在SDK 11 -> 18之间,重用的Bitmap大小必须是一致的。例如给inBitmap赋值的图片大小为100-100,那么新申请的Bitmap必须也为100-100才能够被重用。从SDK 19开始,新申请的Bitmap大小必须小于或者等于已经赋值过的Bitmap大小。
  • 新申请的Bitmap与旧的Bitmap必须有相同的解码格式。例如大家都是8888的,如果前面的Bitmap是8888,那么就不能支持4444与565格式的Bitmap了。我们可以创建一个包含多种典型可重用Bitmap的对象池,这样后续的Bitmap创建都能够找到合适的“模板”去进行重用,如图14所示。

 

 

图14

另外,在2.x的系统上,尽管Bitmap是分配在Native层,但还是无法避免被计算到OOM的引用计数器里。这里提示一下,不少应用会通过反射vBitmapFactory.Options里面的inNativeAlloc来达到扩大使用内存的目的,但是如果大家都这么做,对系统整体会造成一定的负面影响,建议谨慎采纳。

4)避免在onDraw方法里面执行对象的创建

类似onDraw等频繁调用的方法,一定需要注意避免在这里做创建对象的操作,因为他会迅速增加内存的使用,而且很容易引起频繁的gc,甚至是内存抖动。

5)StringBuilder

在有些时候,代码中会需要使用到大量的字符串拼接的操作,这种时候有必要考虑使用StringBuilder来替代频繁的“+”。

内容来源于 小红提技术博客,http://www.xiaohongti.com/ 转载请保留地址,尊重版权。

分享到:
评论

相关推荐

    通过压缩Bitmap来避免OOM

    本文将详细介绍通过压缩Bitmap来避免OOM的相关知识点。 一、Bitmap内存计算 Bitmap在内存中的大小主要由其宽度、高度、颜色模式(如ARGB_8888或RGB_565)以及是否为压缩格式决定。以最常见的ARGB_8888为例,每个...

    Spark面对OOM问题的解决方法及优化总结1

    Spark是大数据处理领域的一款高效计算框架,其内存管理机制对于性能和稳定性至关重要...合理的分区策略、内存管理和资源分配是避免OOM的关键。同时,持续监控和调试Spark应用,可以帮助发现并解决问题,提升整体性能。

    Android OOM错误的原因

    #### 三、如何避免OOM错误 1. **优化Bitmap对象的使用**: - 使用`inSampleSize`属性减少Bitmap的分辨率。 - 尽量使用`BitmapFactory.Options`来预加载和测量图片大小,从而确定合适的内存分配。 - 及时回收不再...

    图片oom,解决方法

    总结来说,解决Android图片OOM问题,需要从图片的大小、加载策略、内存管理等多个方面进行优化。通过合理的图片处理方式和利用现有的优秀库,可以有效地避免和处理图片引起的内存溢出问题,提升应用性能和用户体验。

    android之Gif处理(解决GIF显示容易OOM问题,包括代码和说明),非常详细的介绍

    本篇文章将深入探讨如何在Android中有效地处理GIF,以避免OOM问题。 一、GIF的内存占用问题 GIF是一种基于帧的图像格式,每一帧都是一个完整的图像。当在Android中加载GIF时,如果不做特殊处理,所有帧都会被加载到...

    三级缓存防止OOM大量加载图片的工具类(超强大)

    本文将深入探讨如何利用三级缓存来防止OOM,并详细讲解一个超强大的图片加载工具类。 一、什么是三级缓存 三级缓存通常指的是内存缓存(Memory Cache)、磁盘缓存(Disk Cache)和网络缓存(Network Cache)。当...

    Android 图片压缩不OOM,超高保真度

    在Android开发中,图片处理是一项常见且重要的任务。然而,由于Android系统对内存管理的特性,处理大图时容易导致“Out ...通过这些方法,我们能够在保证图片质量的同时,有效避免OOM问题,提高应用的性能和用户体验。

    Android加载网络图片与本地图片解决OOM问题

    总结来说,解决Android中的图片加载与OOM问题,开发者需要采用合适的图片加载库,如Android-Universal-Image-Loader,利用其提供的内存和磁盘缓存机制、图片解码策略以及异步加载等功能,来优化图片处理过程,提升...

    android Gallery 3d 图片浏览 oom

    总结来说,解决"android Gallery 3d 图片浏览 oom"问题的关键在于优化图片加载流程,合理使用内存和缓存策略,同时注意处理好读取SD卡图片的权限。通过自定义`CustomGallery`,我们可以打造出性能优异、用户体验良好...

    图片下载以及内存处理防OOM.zip

    在Android开发中,图片下载和内存管理是两个关键的环节,尤其对于性能优化和避免内存溢出(Out of Memory, OOM)问题至关重要。本文将深入探讨这些知识点,并结合源码学习来提升Android应用的效率。 一、图片下载 ...

    安卓Android源码——加载本地图片,绝对不会出现OOM.zip

    总结来说,避免Android应用在加载本地图片时出现OOM,需要选择合适的图片加载库,结合合理的内存和磁盘缓存策略,控制图片大小,以及做好资源管理。以上这些技术都是为了在保证用户体验的同时,确保应用的稳定性和...

    JVM优化与OOM分析PPT

    - 将-Xmx和-Xms设置为相同的值4096M,避免每次垃圾回收后重新分配内存; - 设置年轻代大小为1536M,提高年轻代对象的回收效率; - 设置-XX:PermSize=256M和-XX:MaxPermSize=256M来限制永久代的大小; - 设置-XX:+...

    android framework面试题集

    本文总结了 Android Framework 面试题集中的几个重要知识点,包括 Android 应用性能分析、内存泄露和避免 OOM 异常。掌握这些知识点能够帮助开发者更好地编写高性能、低内存占用的 Android 应用程序。

    图片的三级缓存

    总结,"图片的三级缓存"是一个高效且易于集成的解决方案,通过内存、磁盘和本地文件的缓存策略,实现了快速加载和节省资源的目的。ImageHelper和MD5Encoder这两个类的结合使用,使得图片加载过程变得更加智能和高效...

    MySQL OOM 系列一 Linux内存分配

    总结来说,理解Linux内存分配策略,尤其是超额分配的概念,对于解决和预防MySQL OOM问题至关重要。通过调整系统配置、优化数据库性能以及监控系统资源,可以有效地避免MySQL进程因内存耗尽而被杀死的情况。

    关于jsp的一些知识总结

    理解这些内存区域的工作原理对于避免OOM(Out of Memory)错误至关重要。 - 堆内存:存放对象实例,进行垃圾回收。 - 栈内存:每个线程都有独立的栈,存储方法调用的状态。 - 方法区(永久代/元空间):存储类...

    android画图总结

    在内存管理中,需要关注Bitmap的内存占用,避免因过大导致OOM(OutOfMemoryError)。为了优化,可以使用inSampleSize来降低图片分辨率,或者使用Bitmap.Config选择合适的颜色格式。 进入【Android画图学习总结(三...

    ListView异步加载图片和文字,避免内存溢出和滑动效率

    总结,优化ListView的异步加载和内存管理是提升Android应用性能的关键。合理运用上述技术,可以有效避免内存溢出,提高滑动效率,提供更佳的用户体验。同时,不断学习和研究新的优化手段,如利用Android P中的coil库...

    android总结

    【Android 总结】 在Android开发中,优化性能和提高用户体验是至关重要的。本文将深入探讨Handler机制、ListView优化以及图片处理这三个关键知识点。 **Handler机制** Handler是Android消息处理的核心组件,它允许...

Global site tag (gtag.js) - Google Analytics