文档章节

Android加载大背景图或者大量图片时,内存溢出的解决方案

 小牛仔
发布于 2015/01/20 15:55
字数 871
阅读 213
收藏 1

Android在加载大背景图或者大量图片时,经常导致内存溢出(Out of Memory Error),解决方案如下:

一,3种在代码中设置图片方式有区别,最好不使用setImageResource,原因:
(1)setImageResource的参数是resId,必须是drawable目录下的资源.在UI线程中对图片读取和解析的,所以有可能对一个Activity的启动造成延迟。
(2)setImageDrawable参数是Drawable,也是可以接受不同来源的图片,方法中所做的事情就是更新ImageView的图片。
(3)setImageBitmap参数是Bitmap,把Bitmap对象封装成Drawable对象,然后调用setImageDrawable来设置图片。

二,BitmapFactory提供了几种解码方式(decodeByteArray(), decodeFile(), decodeResource(),decodeStream()等等),以便从多种资源中创建一个Bitmap(位图)对象。
建议使用decodeStream(),最节省空间,因为它直接调用JNI>>nativeDecodeAsset()来完成decode,无需再使用java层的createBitmap。

    /**
     * 对一张大图片进行适当的压缩,让它能够以最佳大小显示的同时,还能防止OOM的出现。
     * @param path SD卡中的图片的路径
     * @param reqWidth reqHeight 压缩图片的尺寸,单位是像素(sp)
     */
    public static Bitmap getLimitSizeBitmapFromPath(String path, int reqWidth, int reqHeight) 
      throws IOException{
         //1.加载位图
         FileInputStream is = new FileInputStream(path);
         BitmapFactory.Options opts=new BitmapFactory.Options();
     
         //2.设置位图缩放比例
         opts.inJustDecodeBounds = true;
        // 当inJustDecodeBounds = true时,decodeFile禁止为bitmap分配内存,返回值也不再是一个Bitmap对象,而是null
        // 但是BitmapFactory.Options的outWidth、outHeight和outMimeType属性都会被赋值
        Bitmap bitmap = BitmapFactory.decodeFile(path, opts);
        final int height = opts.outHeight;
        final int width = opts.outWidth;       
        int scale = 1;
        if (height > reqHeight || width > reqWidth) {
           // 计算出实际宽高和目标宽高的比率
           final int heightRatio = Math.round((float) height / (float) reqHeight);
           final int widthRatio = Math.round((float) width / (float) reqWidth);
           // 选择宽和高中最小的比率作为inSampleSize的值,这样可以保证最终图片的宽和高
           // 一定都会大于等于目标的宽和高。
           scale = heightRatio < widthRatio ? heightRatio : widthRatio;
        }
        opts.inSampleSize = scale;
        opts.inJustDecodeBounds = false;
     
        //3.设置位图颜色显示优化方式
        //ALPHA_8:每个像素占用1byte内存(8位)
        //ARGB_4444:每个像素占用2byte内存(16位)
        //ARGB_8888:每个像素占用4byte内存(32位),Android默认的颜色模式,占用的内存也最大
        //RGB_565:每个像素占用2byte内存(16位)
        opts.inPreferredConfig = Bitmap.Config.RGB_565;
 
        //4.设置图片可以被回收,创建Bitmap用于存储Pixel的内存空间在系统内存不足时可以被回收
        opts.inPurgeable = true;
     
        //5.设置解码位图的尺寸信息
        opts.inInputShareable = true;
 
        //6.解码位图:decodeStream是最节省空间的一种方法
        bitmap = BitmapFactory.decodeStream(is, null, opts);
 
        is.close();
        return bitmap;
    }

三,如果使用imageView.setImageBitmap()来加载图片,在Activity或者Fragment在onStop/onDestroy释放图片资源。

if(imageView != null) {

    BitmapDrawable b = (BitmapDrawable)v.getDrawable();

    if(b != null){     

        Bitmap oldBitmap = b.getBitmap();    

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

            oldBitmap.recycle();    

            oldBitmap = null;

        }    

    }

}

四,如果使用imageView.setImageDrawable()来加载图片,在Activity或者Fragment在onStop/onDestroy释放图片资源。

if(imageView != null) {

    Drawable d = (ImageView).getDrawable();

    if (d != null) {

     //清除setImageDrawable(d)对d的引用

     d.setCallback(null);

    }

    ImageView.setImageDrawable(null);

}

此外,介绍下面几个开源框架,都包含了很好的图片缓存功能:

1. thinkandroid:API 4(Android 1.6)以上
项目地址 https://github.com/white-cat/ThinkAndroid

2. Afinal
项目地址 https://github.com/yangfuhai/afinal

3. KJFrameForAndroid: API 11(Android 3.0)以上
项目地址 https://github.com/kymjs/KJFrameForAndroid

4. volley: API 8(Android 2.2)以上
Demo地址 https://github.com/smanikandan14/Volley-demo

5. xUtils框架: API 8(Android 2.2)以上
项目地址:https://github.com/wyouflf/xUtils

6. LoonAndroid: API 8(Android 2.2)以上
项目地址:https://github.com/gdpancheng/LoonAndroid

© 著作权归作者所有

粉丝 0
博文 34
码字总数 35169
作品 0
成都
私信 提问
Android加载图片导致内存溢出(Out of Memory异常)

Android在加载大背景图或者大量图片时,经常导致内存溢出(Out of Memory Error),本文根据我处理这些问题的经历及其它开发者的经验,整理解决方案如下(部分代码及文字出处无法考证): 方...

天下杰论
2013/06/20
6.9K
2
Android性能优化:手把手教你如何让App更快、更稳、更省(含内存、布局优化等)

前言 在 开发中,性能优化策略十分重要 因为其决定了应用程序的开发质量:可用性、流畅性、稳定性等,是提高用户留存率的关键 本文全面讲解性能优化中的所有知识,献上一份 性能优化的详细攻...

Carson_Ho
2018/05/30
0
0
Android应用开发之(你必须知道的“避免内存溢出图片处理方案”)

今天给大家分享一些图片处理常用技术方案,Android应用开发的朋友必须要了解呀! 众所周知在Android应用开发中在对图片处理时,稍有不慎就会出现以下异常: java.lang.OutofMemoryError: bi...

雨焰
2012/10/23
807
0
Android原生PDF功能实现

1、背景 近期,公司希望实现安卓原生端的PDF功能,要求:高效、实用。 经过两天的调研、编码,实现了一个简单Demo,如上图所示。 关于安卓原生端的PDF功能实现,技术点还是很多的,为了咱们安...

齐行超
10/12
0
0
Android原生PDF功能实现:PDF阅读、PDF页面跳转、PDF手势伸缩、PDF目录树、PDF预览缩略图

1、背景 近期,公司希望实现安卓原生端的PDF功能,要求:高效、实用。 经过两天的调研、编码,实现了一个简单Demo,如上图所示。 关于安卓原生端的PDF功能实现,技术点还是很多的,为了咱们安...

齐行超
10/11
0
0

没有更多内容

加载失败,请刷新页面

加载更多

3_数组

3_数组

行者终成事
今天
7
0
经典系统设计面试题解析:如何设计TinyURL(二)

原文链接:https://www.educative.io/courses/grokking-the-system-design-interview/m2ygV4E81AR 编者注:本文以一道经典的系统设计面试题:《如何设计TinyURL》的参考答案和解析为例,帮助...

APEMESH
今天
7
0
使用logstash同步MySQL数据到ES

概述   在生成业务常有将MySQL数据同步到ES的需求,如果需要很高的定制化,往往需要开发同步程序用于处理数据。但没有特殊业务需求,官方提供的logstash就很有优势了。   在使用logstas...

zxiaofan666
今天
10
0
X-MSG-IM-分布式信令跟踪能力

经过一周多的鏖战, X-MSG-IM的分布式信令跟踪能力已基本具备, 特点是: 实时. 只有要RX/TX就会实时产生信令跟踪事件, 先入kafka, 再入influxdb待查. 同时提供实时sub/pub接口. 完备. 可以完整...

dev5
今天
7
0
OpenJDK之CyclicBarrier

OpenJDK8,本人看的是openJDK。以前就看过,只是经常忘记,所以记录下 图1 CyclicBarrier是Doug Lea在JDK1.5中引入的,作用就不详细描述了,主要有如下俩个方法使用: await()方法,如果当前线...

克虏伯
今天
8
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部