一、减小对象的内存占用

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

例如,我们可以考虑使用ArrayMap/SparseArray而不是HashMap等传统数据结构。

ArrayMap和HashMap主要不同之处在于:

1、存储方式不同:ArrayMap内部使用两个数组,一个存HashCode,一个存键值对对象。HashMap内部是Entry对象。

2、扩容方式不同:上面HashMap源码分析这篇文章说过了,HashMap初始大小是16,达到满容量的0.75时,要扩容,每次都是上次容量的2倍。

ArrayMap用的是copy数据,所以效率相对要高。

最后说说使用场景,如果存储数量在千级以下,可以考虑用ArrayMap代替HashMap,但要注意的是,ArrayMap要比HashMap慢。Android里的Bundle内部就是ArrayMap,所以大家可以自行考虑使用。

2)避免在Android里面使用Enum

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

4)使用更小的图片

二、内存对象的重复利用

1)复用系统自带的资源

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

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

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

5)StringBuilder

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

避免对象的内存泄露

1)注意Activity的泄漏

内存对象的泄漏,会导致一些不再使用的对象无法及时释放,这样一方面占用了宝贵的内存空间,很容易导致后续需要分配内存的时候,空闲空间不足而出现OOM。显然,这还使得每级Generation的内存区域可用空间变小,GC就会更容易被触发,容易出现内存抖动,从而引起性能问题。

通常来说,Activity的泄漏是内存泄漏里面最严重的问题,它占用的内存多,影响面广,我们需要特别注意以下两种情况导致的Activity泄漏:

  • 内部类引用导致Activity的泄漏

最典型的场景是Handler导致的Activity泄漏,如果Handler中有延迟的任务或者是等待执行的任务队列过长,都有可能因为Handler继续执行而导致Activity发生泄漏。此时的引用关系链是Looper -> MessageQueue -> Message -> Handler -> Activity。为了解决这个问题,可以在UI退出之前,执行remove Handler消息队列中的消息与runnable对象。或者是使用Static + WeakReference的方式来达到断开Handler与Activity之间存在引用关系的目的。

  • Activity Context被传递到其他实例中,这可能导致自身被引用而发生泄漏。

内部类引起的泄漏不仅仅会发生在Activity上,其他任何内部类出现的地方,都需要特别留意!我们可以考虑尽量使用static类型的内部类,同时使用WeakReference的机制来避免因为互相引用而出现的泄露。

2)考虑使用Application Context而不是Activity Context

对于大部分非必须使用Activity Context的情况(Dialog的Context就必须是Activity Context),我们都可以考虑使用Application Context而不是Activity的Context,这样可以避免不经意的Activity泄露。

3)注意临时Bitmap对象的及时回收

虽然在大多数情况下,我们会对Bitmap增加缓存机制,但是在某些时候,部分Bitmap是需要及时回收的。例如临时创建的某个相对比较大的bitmap对象,在经过变换得到新的bitmap对象之后,应该尽快回收原始的bitmap,这样能够更快释放原始bitmap所占用的空间。

需要特别留意的是Bitmap类里面提供的createBitmap()方法,如图所示:

这个函数返回的bitmap有可能和source bitmap是同一个,在回收的时候,需要特别检查source bitmap与return bitmap的引用是否相同,只有在不等的情况下,才能够执行source bitmap的recycle方法。

4)注意监听器的注销

在Android程序里面存在很多需要register与unregister的监听器,我们需要确保在合适的时候及时unregister那些监听器。自己手动add的listener,需要记得及时remove这个listener。

5)注意缓存容器中的对象泄漏

有时候,我们为了提高对象的复用性把某些对象放到缓存容器中,可是如果这些对象没有及时从容器中清除,也是有可能导致内存泄漏的。例如,针对2.3的系统,如果把drawable添加到缓存容器,因为drawable与View的强应用,很容易导致activity发生泄漏。而从4.0开始,就不存在这个问题。解决这个问题,需要对2.3系统上的缓存drawable做特殊封装,处理引用解绑的问题,避免泄漏的情况。

6)注意WebView的泄漏

Android中的WebView存在很大的兼容性问题,不仅仅是Android系统版本的不同对WebView产生很大的差异,另外不同的厂商出货的ROM里面WebView也存在着很大的差异。更严重的是标准的WebView存在内存泄露的问题,所以通常根治这个问题的办法是为WebView开启另外一个进程,通过AIDL与主进程进行通信,WebView所在的进程可以根据业务的需要选择合适的时机进行销毁,从而达到内存的完整释放。

7)注意Cursor对象是否及时关闭

在程序中我们经常会进行查询数据库的操作,但时常会存在不小心使用Cursor之后没有及时关闭的情况。这些Cursor的泄露,反复多次出现的话会对内存管理产生很大的负面影响,我们需要谨记对Cursor对象的及时关闭。

参考连接:http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2015/0920/3478.html

如何避免OOM的更多相关文章

  1. 【知识必备】内存泄漏全解析,从此拒绝ANR,让OOM远离你的身边,跟内存泄漏say byebye

    一.写在前面 对于C++来说,内存泄漏就是new出来的对象没有delete,俗称野指针:而对于java来说,就是new出来的Object放在Heap上无法被GC回收:而这里就把我之前的一篇内存泄漏的总 ...

  2. ValueInjecter----最好用的OOM(以微信消息转对象举例)

    使用数据实体的好处我这里就不多说了,但大家享受这些好处的时候,难免也对那些琐碎的赋值代码感到厌烦,基于此,我认为掌握一个oom的使用,还是很有必要的. 这种类型的工具有很多,比如automapper, ...

  3. 五步掌握OOM框架AutoMapper基本使用

    本文版权归博客园和作者吴双本人共同所有,转载和爬虫请注明原文地址 www.cnblogs.com/tdws  写在前面 OOM顾名思义,Object-Object-Mapping实体间相互转换,Aut ...

  4. Android设置图片内存溢出(OOM)问题——Android开发进阶之路6

    ImageView设置图片必备常识技术: Android设备会给每个应用分配16M的内存空间,如果你设置的图片的比较大且同一个页面有多个时,经常会报OOM错误导致程序奔溃.所以在这种情况下我们必须要对 ...

  5. MySQL 5.6 OOM 问题解决分享【转】

    本文来自:杨德华的原创分享 | MySQL 5.6 OOM 问题解决分享 延伸阅读:Linux的内存回收和交换 当遇到应用程序OOM的时候,大多数时候只能用头疼来形容,应用程序还可以通过引流来临时重启 ...

  6. Android 内存管理 &Memory Leak & OOM 分析

    转载博客:http://blog.csdn.net/vshuang/article/details/39647167 1.Android 进程管理&内存 Android主要应用在嵌入式设备当中 ...

  7. OOM killer

    Linux下有一种OOM KILLER 的机制,它会在系统内存耗尽的情况下,启用自己算法有选择性的kill 掉一些进程. 1. 为什么会有OOM killer 当我们使用应用时,需要申请内存,即进行m ...

  8. Spark java.lang.outofmemoryerror gc overhead limit exceeded 与 spark OOM:java heap space 解决方法

    引用自:http://cache.baiducontent.com/c?m=9f65cb4a8c8507ed4fece7631046893b4c4380146d96864968d4e414c42246 ...

  9. Redis: OOM command not allowed when used memory > ‘maxmemory’

    现象 日志里出现异常: OOM command not allowed when used memory > 'maxmemory' 原因 内存已满,不允许再存数据了,可以通过redis-cli ...

  10. 总结Android中遇见的OOM

    一 .Android应用中内存泄漏几种的原因: 1.单例模式导致的内存泄漏: 当调用getInstance时,如果传入的context是Activity的context.只要这个单例没有被释放,这个A ...

随机推荐

  1. 深入理解JVM(3)——类加载机制

    1.类加载时机 类的整个生命周期包括了:加载( Loading ).验证( Verification ).准备( Preparation ).解析( Resolution ).初始化( Initial ...

  2. Win10修改编辑文件无法保存怎么办(没有权限)

    Win10修改编辑hosts文件无法保存怎么办 修改一些系统文件无法保存说明这个账户没有“写”这个权限 这里以hosts文件为例,为账户增加读写权限: 首先进入Win10系统的hosts文件所在位置 ...

  3. Stacking:Catboost、Xgboost、LightGBM、Adaboost、RF etc

    python风控评分卡建模和风控常识(博客主亲自录制视频教程) https://study.163.com/course/introduction.htm?courseId=1005214003&am ...

  4. Error creating bean with name

    最近在学一个东西,要使用SSM新建一个案例,是这样滴,我有如下 DeptDAO DeptService DeptServiceImpl DeptController Dept Mybatis 首先,我 ...

  5. python 错误捕获机制分析

    python语言是编程中使用率在Top 3之内的语言.python语言以灵活与简单著称,那么越是灵活的语言越需要判断出错的功力. 简单示例 以下是一个简单的错误程序,被除数不可为0,那么看看该代码的执 ...

  6. 深入浅出mybatis之映射器

    目录 概述 XML映射器 定义xml映射器 配置xml映射器 使用xml映射器 接口映射器 定义接口映射器 配置接口映射器 使用接口映射器 总结与对比 概述 映射器是MyBatis中最核心的组件之一, ...

  7. API.day01

    第1部分 JDK API 1.1 API(Application Programming Interface,应用接口程序):已经封装好可以直接调用的功能(Java中以类的形式封装) 经常使用的JDK ...

  8. 四十三、Linux 线程——线程同步之线程信号量

    43.1 信号量 43.1.1 信号量介绍 信号量从本质上是一个非负整数计数器,是共享资源的数目,通常被用来控制对共享资源的访问 信号量可以实现线程的同步和互斥 通过 sem_post() 和 sem ...

  9. 非旋 treap 结构体数组版(无指针)详解,有图有真相

    非旋  $treap$ (FHQ treap)的简单入门 前置技能 建议在掌握普通 treap 以及 左偏堆(也就是可并堆)食用本blog 原理 以随机数维护平衡,使树高期望为logn级别, FHQ  ...

  10. Ubuntu18.04 LTS 安装部署golang最新版本1.10

    1 步骤 //1 直接安装golang-go 目前最新版本是1.10 sudo apt-get install golang-go //2 向/etc/profile追加以下代码 sudo vim / ...