android避免OOM的几种常见方式

一、说起OOM,可能有的人会说,现在手机的运行内存这么大,再加上Android系统还自带了GC机制,怎么还会有OOM这回事呢?

首先,手机的运行内存不会全部分配给你的APP,而是系统会给手机上的每个APP都会限制一个固定大小的内存空间,为了保证同时可以多个进程运行,而不会只为了保证某一个APP的运行而强制关掉其他进程,当然,现在的手机运行内存是越来越大,但是手机上面安装的应用也越来越多了,这样分配给每个应用的内存也不会很多,具体数据可以通过activityManager.getMemoryClass()来获取;

其次,GC机制只在内存空间紧张的时候才会被触发,也就是系统分配给该应用的内存空间所剩不多的时候,才会回收掉系统认为不会使用的对象和软引用,如果应用突然在短时间内申请了很大的内存空间,而这个空间已经超过了剩余内存,这个时候GC机制来没来得及触发,或者触发后内存仍然不够用,这个时候就会报OOM了。


二、哪些情况会导致OOM呢?

1、目前来看,最占内存空间的应该是图片资源,每个图片资源所占的内存大小是可以计算出来的:图片的宽度像素x图片的长度像素x每个像素点所占的bit值。最后一个值由图片的解码格式(decode format)决定,对应关系如下:


ARGB_8888    32Bits/Pixel

RGB_565        16Bits/Pixel

ARGB_4444    16Bits/Pixel

ALPHA_8         8Bits/Pixel


当然,解码格式所占的bit值越大图片看上去越清晰。如果是一张200x200,解码格式是8888的照片,需要的内存大小就是1.28MB,对于目前主流的1080x1920屏幕的手机来说,一个屏幕可以显示40多张这种尺寸图片,那就是50MB左右的内存,事实上图片多的时候肯定还不止这些,这时候滑动屏幕继续展示,如果不使用缓存回收等机制,内存在短时间消耗就非常大,并且跟屏幕滑动得快慢成正比增加,很容易超出分配给应用的内存,导致OOM;

针对以上的问题,可以分下面几个方面来应对:

a、在不影响观看效果的前提下,尽量采用占位小的解码格式;

b、尽量控制在同一个屏幕显示的照片数量,图片太密集了也会影响体验;

c、采用图片缓存机制,比如Android推荐的LRU Cache机制,分配一个指定大小的内存空间用作图片缓存,缓存空间快满的时候释放掉最早加载进来的图片对象,达到循环使用缓存空间的目的;

d、复用bitmap对象,加载下一张或者下个屏幕图片的时候,不重新申请分配内存,而是使用之前图片使用过的内存空间,比如谷歌提供的glide框架;

e、如果原图的尺寸很大,可以采用同比例压缩尺寸的方式显示为小尺寸图片,注意在压缩的过程中先将option的inJustDecodeBounds设置为true,这样获取原图片的尺寸就不需要分配内存了;

f、对不会再使用的bitmap对象设置为null或者recycle,这步可以交给缓存机制去处理。

2、item信息量比较多的listview。原因是listview加载每个item信息时都会同时加载item的布局,生成新的contentView,这样item加载多了也很消耗内存。

解决的原理跟图片对象复用差不多,也是做到复用之前创建的contentView对象,并利用viewholder类来缓存item里面的控件,不用每次加载布局都要findViewById。

3、以上是主要造成OOM的原因,还有一些小细节也能消耗掉一些内存空间:

a、static变量的过多使用。static变量属于全局变量,直到应用程序关闭才被回收,如果使用频率过多,会造成内存的不断消耗;

b、自定义view的时候,在onDraw()方法里面创建对象。这个方法会随着屏幕刷新不断被调用,这样就会反复创建大量的对象,造成内存消耗的累积;

c、对于小数量级,Android推荐使用ArrayMap或者SparseArray来代替HashMap,前者的效率更高,占用内存更少。


基本就是本着重复利用的原则,既然不能开源只好节流,在有限的内存范围内去办更多的事情。


以上,是个人的一点理解,欢迎探讨!

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值