• Android加载图片OOM错误解决方式


    前几天做项目的时候,甲方要求是PAD (SAMSUNG P600 10.1寸 2560*1600)的PAD上显示高分辨率的大图片。

    SQLITE採用BOLD方式存储图片,这个存取过程就不说了哈,网上一大堆。

    可是在加载/读取/显示图片的时候会报OOM错误,上网查了非常多解决方式还绕了非常多弯路,最后还是找到了原因所在。以下从几个方面来解释一下OOM问题的解决方式。

    (谢谢周同学的“尺寸”提醒。不然我可能一辈子都要蒙在鼓里)

    1.Android APP内存

    做一个APP开发的时候,还是不要想着去扩大Android系统赋予的内存上限了。部分老机型老系统16M。大部分都是24M了。

    一些大型游戏用dalvik.system.VMRuntime来干涉GC过程(这个类我还没有学过。

    。刚听说不久)。

    据说用NDK开发时候,C能够动态申请多余的内存空间,可是我没用过NDK,今后也不打算用了(个人原因)。

     

    2.图片文件大小

    甲方给了一大堆文件大小不一的图片,在加载数据库->读取出来->显示出来的这个过程中,出现了非常多OOM,分为:

    a.加载图片时使用ByteArrayStream创建流,size为Height * Width * 4。OOM;

    b.读取图片时候OOM,同上;

    c.显示图片时候OOM,decodeResource函数报错,OOM;

    開始时候以为是文件大小问题。后来发现有些2M的图片都能显示,可是某些1M的图片确报错。所以在一定范围内,能够证明。图片OOM问题与文件大小无关。

     

    3.图片尺寸(分辨率)

    调查这些能显示的图片和不能显示的图片的不同。发现长宽差距非常大。那些能成功显示的图片为1005*1500大小,而其它图片都是3000*5000以上。

    我用PAINT(一款适合小白的图像处理软件。尽管不如PS可是功能已经很强大了,最新版须要安装NET 4.5)压缩了图片大小。压缩到1005*1500。显示成功。

     

    4.函数调用

    阅读了这位大神的博客:

    http://blog.csdn.net/huangbiao86/article/details/8072128

    摘取当中最精华的部分吧:

    尽量不要使用setImageBitmap或setImageResource或BitmapFactory.decodeResource来设置一张大图,由于这些函数在完毕decode后。终于都是通过java层的createBitmap来完毕的。须要消耗很多其它内存。

     

    因此,改用先通过BitmapFactory.decodeStream方法,创建出一个bitmap,再将其设为ImageView的 source,decodeStream最大的秘密在于其直接调用JNI>>nativeDecodeAsset()来完毕decode。无需再使用java层的createBitmap,从而节省了java层的空间。


    假设在读取时加上图片的Config參数,能够跟有效降低载入的内存。从而跟有效阻止抛out of Memory异常


    另外。decodeStream直接拿的图片来读取字节码了。 不会依据机器的各种分辨率来自己主动适应, 使用了decodeStream之后,须要在hdpi和mdpi,ldpi中配置对应的图片资源, 否则在不同分辨率机器上都是相同大小(像素点数量),显示出来的大小就不正确了。

    看来读底层源代码还是非常实用的,setImageBitmap 和 setImageResource 和 decodeResource在运行过程中还是调用了createBitmap来创建一个新的bitmap。创建bitmap会加剧内存消耗,所以不推荐使用了。应该使用decodeStream方法。

    图片的压缩过程也能够设置一个合适的百分比来控制大小。

    多张图片的使用中,请注意流的flush与close(我没有及时flush和close的时候也执行正确了,这个有待研究一下,可是为了保证一个良好的习惯还是注意下吧)。

     

    5.关于options方法

    网上还有非常多文章用BitmapFactory.Options来作为decodeStream时候的一个參数,这个我临时没有详细实验过,哪位朋友实验过了能够回复交流哈

  • 相关阅读:
    python 数据类型 变量 注释
    tornado 模版
    tornado 响应头 中断 状态码 工作流程
    tornado write render redirect IP
    tornado样板
    Celery实现异步任务
    Python pika简单实现RabbitMQ通信
    进程、线程与协程的比较
    使用 flask 实现 RESTful API
    阿里云服务器部署Tornado应用
  • 原文地址:https://www.cnblogs.com/lcchuguo/p/5240992.html
Copyright © 2020-2023  润新知