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

来源:互联网 发布:数据单位从小到大排列 编辑:程序博客网 时间:2024/04/27 21:07

大家好,今天给大家分享的是解决解析图片的出现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。

OK,今天就讲到这里,大家有什么疑问的,可以留言,谢谢大家!!!

源代码点击进入==>
0 0
原创粉丝点击