• [置顶] 解决Android解析图片的OOM问题


    转自Android_Tutor csdn博客:

    大家好,今天给大家分享的是解决解析图片的出现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,今天就讲到这里,大家有什么疑问的,可以留言,谢谢大家!!!

    源代码点击进入==>

  • 相关阅读:
    NOI2017 退役记
    bzoj2590[Usaco2012 Feb]Cow Coupons
    bzoj2215[POI2011]Conspiracy
    bzoj2115[WC2011]Xor
    bzoj4754[JSOI2016]独特的树叶
    SQL外连接与条件 left outer join + WHERE/AND 区别
    IBM Datastage
    无法在MS SQL SERVER MANAGEMENT中打开SSIS实例-解决办法
    SSIS 教学教程
    SQL SERVER 2019 电子书下载
  • 原文地址:https://www.cnblogs.com/anjon520/p/3249956.html
Copyright © 2020-2023  润新知