美文网首页基础Android技术知识Android知识
Android OOM异常的快捷常规处理方法

Android OOM异常的快捷常规处理方法

作者: Rayhaha | 来源:发表于2017-01-19 11:46 被阅读812次

    整理一下平时自己对于Android OOM异常的常规处理方法:


    什么是OOM?

    OutOfMemory(内存溢出):不良代码创建了【太大或太多的对象实例】,且用完没有及时释放,导致运行内存超过了系统分配的上限(爆内存),从而使应用异常退出的现象

    然后解决方法有很多,根据需求和应用场景不同,处理方法也各有不同


    目录:

    -1、及时释放Bitmap资源

    -2、加载Bitmap时Options的设置

    -3、使用decodeStream代替decodeResource

    -4、使用软引用持有资源

    -5、三级缓存策略


    第一种:及时释放Bitmap资源

    /**

    * 释放Bitmap资源

    */

    public voidrecycleBitmap() {

    Bitmap bitmap = BitmapFactory.decodeFile(PATH_NAME);

    if(bitmap !=null&& !bitmap.isRecycled()) {

    bitmap.recycle();

    bitmap =null;

    }

    System.gc();

    }

    需要注意的是:

    bitmap本身调用recycle()也是相当于通过呼叫垃圾回收器来回收资源,并不是立刻释放资源的。

    而且在Android2.3以及更低的版本中,Bitmap的引用是放在堆中的,而Bitmap的数据部分是放在栈中的,需要用户调用recycle方法手动进行内存回收

    而在Android2.3之后,整个Bitmap,包括数据和引用,都放在了堆中,这样,整个Bitmap的回收就全部交给GC了,这个recycle方法就再也不需要使用了。

    对于Bitmap.recycle的更加详细的说法可以去看下面这个连接:

    http://hukai.me/android-training-course-in-chinese/graphics/displaying-bitmaps/manage-memory.html


    第二种:创建Bitmap时,Options的设置:

    1、颜色模式设置:inPreferredConfig

    ·ALPHA_8——只有透明度通道,占用一个字节8位,有256个不同透明度梯度 ,连图片都看不见了。。。。

    ·ARGB_4444——有透明度和红绿蓝四个通道,每像素占用2字节16位,每个通道占用4位,即16种不同梯度,显示效果较差

    ·ARGB_8888——有透明度和红绿蓝四个通道,每像素占用4字节32位,每个通道占用8位,即256种不同梯度,显示效果好,是安卓默认的颜色模式

    ·RGB_565——有红绿蓝三个通道,每像素占用2字节16位,红绿蓝分别占5、6、6位,即32种不同梯度,但是不具备透明通道,是一种常用的效果和开销都比较折中的颜色模式

    2、采样率inSampleSize

    -图片上的像素越多,显示图片的内存开销也就越高

    -设置采样率,就可以让图片均匀地丢掉图片的一些像素,既能完整显示图片,又能降低图片的开销

    -采样率的设置只能是:2的整数幂,2,4,8..... ,当设置为4的时候,只均匀采集原有1/4的像素

    -所以,通常设置采样率来进行二次采样来降低图片的内存开销会是有效地做法

    3、解码大小inJustDecodeBounds

    -很多时候我们都不需要图片的完整显示,仅仅需要他的部分属性的时候,我们就可以将这个属性设置为true

    -这个时候图片就不会去加载图片的位图信息,只会返回图片宽高信息并放进Options里面的供我们使用。

    -可以通过options.outHeight和options.outWidth来使用

    -搭配inSampleSize来使用:

    首先用inJustDecodeBounds来确定图片的大小,然后使用inJustDecodeBounds来设置应该压缩的宽高,从而达到内存优化

    代码如图:

    Options设置

    第三种:

    使用BitmapFactory.decodeStream:

    -通常我们在加载本地图片资源的时候会使用decodeResource()方法

    -但是我们在追溯源码的时候发现了这样一个关系

    -decodeResource() --> decodeResourceStream() --> decodeStream() --> native

    -然后我们可以看到decodeResourceStream()源码如下:

    decodeResourceStream源码

    -由此,我们发现了

    -decodeResource在解析时会对Bitmap根据当前设备屏幕像素密度densityDpi的值进行缩放适配操作

    - 使得解析出来的Bitmap与当前设备的分辨率匹配,达到一个最佳的显示效果,并且Bitmap的大小将比原始的大

    更加详细的描述可以参考:

    http://www.androidchina.net/4532.html?utm_source=tuicool&utm_medium=referral

    - 所以得出的结论是:

    -尽量多的使用decodeStream来加载图片资源

    -使用如下:

    decodeStream使用

    第四种:

    使用软引用持有资源:

    普通的Bitmap对象都是强引用对象,正在使用时难以释放资源造成OOM

    所以使用软引用来代替强引用,以达到在内存不足的情况下会强制释放部分资源,以保持程序的正常运行

    具体的代码如下:

    软引用


    第五种:

    三级缓存策略:

    -很多时候我们需要从网上去加载图片资源

    -为了防止过多的访问网络资源,而导致流量使用过大,而采取的一种图片资源加载策略

    --策略如图:

    三级缓存策略

    --代码实现如图:

    三级缓存策略实现

    PS:网络加载图片和文件写入图片不是本篇的重点,我就直接使用以前封装好的工具类了



    最后:

    -这里的代码我只是做了一个基本的使用演示

    -加以完善封装的话就可以形成一个你自己的图片压缩处理的工具类了

    -这些只是我在之前学习和工作中总结的一些常规使用技巧

    -如果有写的不好,或者理解错误的地方,希望大家可以指出来


    补充:

    我的Github : https://github.com/Rayhahah/BitmapOOM.git

    相关文章

      网友评论

      本文标题:Android OOM异常的快捷常规处理方法

      本文链接:https://www.haomeiwen.com/subject/ejkibttx.html