解决Android解析图片的OOM问题!!!

原创 2015年11月18日 14:57:14

大家好,今天给大家分享的是解决解析图片的出现oom的问题,我们可以用BitmapFactory这里的各种Decode方法,如果图片很小的话,不会出现oom,但是当图片很大的时候

就要用BitmapFactory.Options这个东东了,Options里主要有两个参数比较重要.

[java] view plaincopy
  1. options.inJustDecodeBounds = false/true;  
  2. //图片压缩比例.  
  3. options.inSampleSize = ssize;  

我们去解析一个图片,如果太大,就会OOM,我们可以设置压缩比例inSampleSize,但是这个压缩比例设置多少就是个问题,所以我们解析图片可以分为俩个步骤,第一步就是

获取图片的宽高,这里要设置Options.inJustDecodeBounds=true,这时候decode的bitmap为null,只是把图片的宽高放在Options里,然后第二步就是设置合适的压缩比例inSampleSize,这时候获得合适的Bitmap.这里我画了简单的流程图,如下:


为了让大家更容易理解,我这里做了一个简单的demo,主要功能就是一个界面里有个ImageView,点击ImageView的时候,进入本地相册,选择一个图片的时候,ImageView控件显示选择的图片。Demo的步骤如下:

第一步新建一个Android工程命名为ImageCacheDemo.目录结构如下:


第二步新建一个ImageCacheUtil.java工具类,代码如下:

[java] view plaincopy
  1. package com.tutor.oom;  
  2. import java.io.InputStream;  
  3.   
  4. import android.content.ContentResolver;  
  5. import android.content.Context;  
  6. import android.graphics.Bitmap;  
  7. import android.graphics.BitmapFactory;  
  8. import android.graphics.BitmapFactory.Options;  
  9. import android.net.Uri;  
  10.   
  11. /** 
  12.  * @author frankiewei. 
  13.  * 工具类. 
  14.  */  
  15. public class ImageCacheUtil {  
  16.   
  17.     /** 
  18.      * 获取合适的Bitmap平时获取Bitmap就用这个方法吧. 
  19.      * @param path 路径. 
  20.      * @param data byte[]数组. 
  21.      * @param context 上下文 
  22.      * @param uri uri 
  23.      * @param target 模板宽或者高的大小. 
  24.      * @param width 是否是宽度 
  25.      * @return 
  26.      */  
  27.     public static Bitmap getResizedBitmap(String path, byte[] data,  
  28.             Context context,Uri uri, int target, boolean width) {  
  29.         Options options = null;  
  30.   
  31.         if (target > 0) {  
  32.   
  33.             Options info = new Options();  
  34.             //这里设置true的时候,decode时候Bitmap返回的为空,  
  35.             //将图片宽高读取放在Options里.  
  36.             info.inJustDecodeBounds = false;  
  37.               
  38.             decode(path, data, context,uri, info);  
  39.               
  40.             int dim = info.outWidth;  
  41.             if (!width)  
  42.                 dim = Math.max(dim, info.outHeight);  
  43.             int ssize = sampleSize(dim, target);  
  44.   
  45.             options = new Options();  
  46.             options.inSampleSize = ssize;  
  47.   
  48.         }  
  49.   
  50.         Bitmap bm = null;  
  51.         try {  
  52.             bm = decode(path, data, context,uri, options);  
  53.         } catch(Exception e){  
  54.             e.printStackTrace();  
  55.         }  
  56.         return bm;  
  57.   
  58.     }  
  59.       
  60.     /** 
  61.      * 解析Bitmap的公用方法. 
  62.      * @param path 
  63.      * @param data 
  64.      * @param context 
  65.      * @param uri 
  66.      * @param options 
  67.      * @return 
  68.      */  
  69.     public static Bitmap decode(String path, byte[] data, Context context,  
  70.             Uri uri, BitmapFactory.Options options) {  
  71.   
  72.         Bitmap result = null;  
  73.   
  74.         if (path != null) {  
  75.   
  76.             result = BitmapFactory.decodeFile(path, options);  
  77.   
  78.         } else if (data != null) {  
  79.   
  80.             result = BitmapFactory.decodeByteArray(data, 0, data.length,  
  81.                     options);  
  82.   
  83.         } else if (uri != null) {  
  84.             //uri不为空的时候context也不要为空.  
  85.             ContentResolver cr = context.getContentResolver();  
  86.             InputStream inputStream = null;  
  87.   
  88.             try {  
  89.                 inputStream = cr.openInputStream(uri);  
  90.                 result = BitmapFactory.decodeStream(inputStream, null, options);  
  91.                 inputStream.close();  
  92.             } catch (Exception e) {  
  93.                 e.printStackTrace();  
  94.             }  
  95.   
  96.         }  
  97.   
  98.         return result;  
  99.     }  
  100.       
  101.       
  102.     /** 
  103.      * 获取合适的sampleSize. 
  104.      * 这里就简单实现都是2的倍数啦. 
  105.      * @param width 
  106.      * @param target 
  107.      * @return 
  108.      */  
  109.     private static int sampleSize(int width, int target){             
  110.             int result = 1;           
  111.             for(int i = 0; i < 10; i++){               
  112.                 if(width < target * 2){  
  113.                     break;  
  114.                 }                 
  115.                 width = width / 2;  
  116.                 result = result * 2;                  
  117.             }             
  118.             return result;  
  119.         }  
  120. }  

第三步:修改ImageCacheDemoActivity.java代码如下:

[java] view plaincopy
  1. package com.tutor.oom;  
  2.   
  3. import android.app.Activity;  
  4. import android.content.Intent;  
  5. import android.graphics.Bitmap;  
  6. import android.os.Bundle;  
  7. import android.provider.MediaStore;  
  8. import android.view.View;  
  9. import android.view.View.OnClickListener;  
  10. import android.widget.ImageView;  
  11.   
  12. /** 
  13.  * @author frankiewei. 
  14.  * 解决图片普通OOM的Demo. 
  15.  */  
  16. public class ImageCacheDemoActivity extends Activity {  
  17.      
  18.       
  19.     /** 
  20.      * 显示图片的ImageView. 
  21.      */  
  22.     private ImageView mImageView;  
  23.       
  24.     /** 
  25.      * 打开本地相册的requestcode. 
  26.      */  
  27.     public static final int OPEN_PHOTO_REQUESTCODE =  0x1;  
  28.       
  29.     /** 
  30.      * 图片的target大小. 
  31.      */  
  32.     private static final int target = 400;  
  33.       
  34.       
  35.     @Override  
  36.     public void onCreate(Bundle savedInstanceState) {  
  37.         super.onCreate(savedInstanceState);  
  38.         setContentView(R.layout.main);  
  39.           
  40.         setupViews();  
  41.     }  
  42.       
  43.     private void setupViews(){  
  44.         mImageView = (ImageView)findViewById(R.id.imageview);  
  45.         mImageView.setOnClickListener(new OnClickListener() {  
  46.               
  47.             public void onClick(View v) {  
  48.                 openPhotos();             
  49.             }  
  50.         });  
  51.     }  
  52.       
  53.     /** 
  54.      * 打开本地相册. 
  55.      */  
  56.     private void openPhotos() {  
  57.   
  58.         Intent intent = new Intent(Intent.ACTION_PICK, null);  
  59.         intent.setDataAndType(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,  
  60.                 "image/*");  
  61.   
  62.         startActivityForResult(intent, OPEN_PHOTO_REQUESTCODE);  
  63.   
  64.     }  
  65.       
  66.     @Override  
  67.     protected void onActivityResult(int requestCode, int resultCode, Intent data) {  
  68.         switch (requestCode) {  
  69.         case OPEN_PHOTO_REQUESTCODE:  
  70.             if(resultCode == RESULT_OK){  
  71.                 //如果用这个方法,Options为null时候,就是默认decode会出现oom哦.  
  72.                 //Bitmap bm = ImageCacheUtil.decode(null, null,   
  73.                 //      ImageCacheDemoActivity.this, data.getData(), null);  
  74.                   
  75.                 //这里调用这个方法就不会oom.屌丝们就用这个方法吧.  
  76.                 Bitmap bm = ImageCacheUtil.getResizedBitmap(nullnull,   
  77.                         ImageCacheDemoActivity.this, data.getData(), target, false);  
  78.                 mImageView.setImageBitmap(bm);  
  79.             }  
  80.               
  81.             break;  
  82.   
  83.         default:  
  84.             break;  
  85.         }  
  86.         super.onActivityResult(requestCode, resultCode, data);  
  87.     }  
  88. }  

其中main.xml布局代码如下:

[java] view plaincopy
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     android:layout_width="fill_parent"  
  4.     android:layout_height="fill_parent"  
  5.     android:orientation="vertical" >  
  6.   
  7.     <TextView  
  8.         android:layout_width="fill_parent"  
  9.         android:layout_height="wrap_content"  
  10.         android:text="@string/hello" />  
  11.       
  12.     <ImageView  
  13.         android:id="@+id/imageview"   
  14.         android:layout_width="400px"  
  15.         android:layout_height="400px"  
  16.         android:src="@drawable/ic_launcher"  
  17.         />  
  18.   
  19. </LinearLayout>  

第四步运行上述工程,效果如下:

   

从本地相册选择显示。用了getRsizedBitmap()方法,图片很大不会oom.


运用默认的decode方法就会oom。

版权声明:本文为博主原创文章,未经博主允许不得转载。

android播放帧动画OOM问题解决

近来在写项目时,有遇到使用android原生的序列帧动画时,在部分手机(尤其是内存小的)上出现了OOM问题,这种问题是不可避免的。1.我觉首先你要看看是否有适配问题,因为你选择播放的图片要是没有放入对...
  • ss8860524
  • ss8860524
  • 2016年01月19日 17:12
  • 3059

android图片加载导致的OOM分析及有效解决办法(BitmapUtils)

android应用尤其是涉及到很多图片处理的经常会遇到OOM(Out Of Memory),为什么会导致OOM,又该如何解决呢?OOM原因分析:android每一个应用都有一个独立的进程,每个进程都是...
  • wlong610
  • wlong610
  • 2016年04月25日 22:08
  • 1766

Andorid Volley框架加载图片OOM问题分析

Android volley 引起的context 上下文 内存泄露,导致的OOM问题分析解决
  • hlglinglong
  • hlglinglong
  • 2015年01月06日 14:53
  • 2922

安卓加载图片过大而导致OOM内存溢出的解决方法(巨坑....)

如果图片太大会造成OOM内存溢出的错误,需要用Bitmap的压缩机制。 如果跳转的页面含有图片可能会导致跳转失败。 比如说我这里是一旦触发了某个按键,就修改该xml的图片和文字说明 则setIm...
  • fengsigaoju
  • fengsigaoju
  • 2016年05月24日 20:55
  • 463

Android 中解决图片加载OOM 之 bitmap 压缩显示,压缩上传

java.lang.OutOfMemoryError OOM就是内存溢出,即Out Of Memory。也就是说内存占有量超过了VM所分配的最大。 现在的手机照相功能强大图片的大小往往达到好几...
  • u012889434
  • u012889434
  • 2015年11月08日 17:47
  • 1096

Android随记------OOM之痛(图片篇)

近段时间一直在折腾Bitmap相关的内存溢出问题,就调试解决中的感受和经验做个简单的总结。 (关于Bitmap的内存消耗机制就不作详细说明,大概就是Bitmap关系到的内存是native heap,...
  • sevensundark
  • sevensundark
  • 2012年05月11日 16:09
  • 6884

解决Bitmap中的OOM问题

http://lcd.yesky.com/imagelist/2009/315/qwm3qsg1r0l9.jpg  这张网络图片非常大,如果直接用BitmapFactory.decodeStream(...
  • a859522265
  • a859522265
  • 2012年09月24日 14:55
  • 4083

Android逐帧动画,逐帧动画加载图片过多时OOM异常的解决和替代方法

1.首先添加逐帧动画播放逐帧动画,在工程中res目录下创建一个anim文件夹,添加动画anim_welcome.xml文件如下: ...
  • MyronChi
  • MyronChi
  • 2015年05月29日 10:17
  • 3353

android ViewPager自动播放OOM处理——轮播制作(五)

android ViewPager自动播放OOM处理——轮播制作(五) 在制作轮播的过程中遇到的OOM问题,再次记录一下解决的过程。...
  • wild46cat
  • wild46cat
  • 2016年09月21日 14:47
  • 475

Android内存溢出整理总结 OOM(Out Of Memory) 加载的图片太多或图片过大时经常出现OOM问题

Android内存溢出整理总结 OOM(Out Of Memory) 加载的图片太多或图片过大时经常出现OOM问题加载的图片太多或图片过大时经常出现OOM问题,找网上资料也提供了很多方法,整理下: ...
  • west8623
  • west8623
  • 2016年03月03日 14:40
  • 1381
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:解决Android解析图片的OOM问题!!!
举报原因:
原因补充:

(最多只允许输入30个字)