Android下导入大图片出现OutOfMemory的解决方案

PhoneGap是很棒的一个跨平台移动开发解决方案。该方案提供了一系列主流平台的底层封装,使得我们可以使用简单的HTML5 + javascript开展跨平台的移动应用开发,从而重用了我们传统应用开发的技能。

目前该团队已经被Adobe收购,并贡献给了Apache,重新命名为Apache Callback(这烂名字怎么来的,怎么就让人感觉不到其价值呢)。目前还在孵化器。

 

Apache链接:http://incubator.apache.org/projects/callback.html

Github:https://github.com/callback/

 

 

在初步的使用过程中发现一个比较严重的问题,是这样的。

我们加载图片经常使用的Android SDK API是:BitmapFactory.decodeStream。

其思路是先decode为bitmap然后简单设置ImageView的src即可,简单方便。

 

然而大家也都知道,现在的摄像机像素,简直是朝着存储不要钱,逼真不要命的方向发展,其图片小则几m大则几十m。

问题就这样来了,decodeSteam的时候,动不动就会抛出OutOfMemory的异常,然后force close。

 

 

怎么解决呢,查了一些资料,最终得到近乎完美的解决。

 

首先我们要明确我们输出的宽度或高度。如果我们不进行合理的缩放,倔强地要一股脑儿加载到JVM(哦,GOOGLE不喜欢这名字,改名叫Dalvik VM)的话,没辙,还是必死无疑,毕竟房子就这么大,非要挤进去,爆棚是必须的了。所以指定合理的高度或者宽度,是必须的——其实几十m的图片挤在一个几英寸的屏幕,压根也不会显得更好看些。

 

然后要进行合理sacle比例的计算,确定接近大小的scaled图片。

 

最后再encodeStream,转换为Bitmap。

 

当然了,如果要resize的更精准,也是可以的,这一步可选了。

 

 

下面是safeDecodeStream,用以替代默认的BitmapFactory.decodeStream。

 

Java代码   收藏代码
  1. /** 
  2.      * A safer decodeStream method 
  3.      * rather than the one of {@link BitmapFactory} 
  4.      * which will be easy to get OutOfMemory Exception 
  5.      * while loading a big image file. 
  6.      *  
  7.      * @param uri 
  8.      * @param width 
  9.      * @param height 
  10.      * @return 
  11.      * @throws FileNotFoundException 
  12.      */  
  13.     protected Bitmap safeDecodeStream(Uri uri, int width, int height)  
  14.     throws FileNotFoundException{  
  15.         int scale = 1;  
  16.         BitmapFactory.Options options = new BitmapFactory.Options();  
  17.         android.content.ContentResolver resolver = this.ctx.getContentResolver();  
  18.           
  19.         if(width>0 || height>0){  
  20.             // Decode image size without loading all data into memory  
  21.             options.inJustDecodeBounds = true;  
  22.             BitmapFactory.decodeStream(  
  23.                     new BufferedInputStream(resolver.openInputStream(uri), 16*1024),  
  24.                     null,  
  25.                     options);  
  26.               
  27.             int w = options.outWidth;  
  28.             int h = options.outHeight;  
  29.             while (true) {  
  30.                 if ((width>0 && w/2 < width)  
  31.                         || (height>0 && h/2 < height)){  
  32.                     break;  
  33.                 }  
  34.                 w /= 2;  
  35.                 h /= 2;  
  36.                 scale *= 2;  
  37.             }  
  38.         }  
  39.   
  40.         // Decode with inSampleSize option  
  41.         options.inJustDecodeBounds = false;  
  42.         options.inSampleSize = scale;  
  43.         return BitmapFactory.decodeStream(  
  44.                 new BufferedInputStream(resolver.openInputStream(uri), 16*1024),   
  45.                 null,   
  46.                 options);  
  47.     }     

对了,我提了一个enhancement给Apache Callback.

链接:https://issues.apache.org/jira/browse/CB-14

 

需要指出的是,这里的参数Uri如果你觉得不方面,完成可以提供系列可选参数,比如

1. String fileName - 指定文件路径

2. URL

3. InputStream

4. etc.

 

仅供参考。谢谢!

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值