android 加载大图片处理

   转载自:http://blog.csdn.net/xu_fu/article/details/8262153

   在Android中显示图片一般使用ImageView,通过setImageBitmap()、setImageResource()等方法指定要显示的方法,而这些方法最终都会调用到BitmapFactory.decode()方法来生成一个Bitmap进行显示。对于一般的小图片这样使用没有什么问题,因为垃圾回收器会及时将不用的图片进行回收,但连续加载大图片的时候就会发生典型的OOM问题,也就是内存溢出,这是因为在Android系统中虚拟机为每一个应用程序都分配了指定内存大小,如果使用超出了这个限制就会发生内存溢出导致程序崩溃。

        因此要避免OOM的问题就需要对大图片的加载进行管理,主要通过缩放来减小图片的内存占用。

1、Bitmap的缩放

生成Bitmap都要通过BitmapFactory的decode()方法,使用此方法时可以传入一个解析参数BitmapFactory.Option来对控制解析过程,比如获得长宽、改变采样率、改变采样格式等。而对Bitmap的缩放就是通过改变采样率来实现的,具体操作如下:

1)计算实际采样率

[java]  view plain copy print ?
  1. public static int calculateInSampleSize(BitmapFactory.Options options,  
  2.             int reqWidth, int reqHeight) {  
  3.         // Raw height and width of image  
  4.         final int height = options.outHeight;  
  5.         final int width = options.outWidth;  
  6.         int inSampleSize = 1;  
  7.   
  8.         if (height > reqHeight || width > reqWidth) {  
  9.             if (width > height) {  
  10.                 inSampleSize = Math.round((float) height / (float) reqHeight);  
  11.             } else {  
  12.                 inSampleSize = Math.round((float) width / (float) reqWidth);  
  13.             }  
  14.   
  15.         return inSampleSize;  
  16.     }  

2)由得到的采样率对图片进行解析

[java]  view plain copy print ?
  1. public static Bitmap decodeSampledBitmapFromFile(String filename,  
  2.             int reqWidth, int reqHeight) {  
  3.   
  4.         // First decode with inJustDecodeBounds=true to check dimensions  
  5.         final BitmapFactory.Options options = new BitmapFactory.Options();  
  6.         options.inJustDecodeBounds = true;  
  7.         BitmapFactory.decodeFile(filename, options);  
  8.   
  9.         // Calculate inSampleSize  
  10.         options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);  
  11.   
  12.         // Decode bitmap with inSampleSize set  
  13.         options.inJustDecodeBounds = false;  
  14.         return BitmapFactory.decodeFile(filename, options);  
  15.     }  

这样就可以对图片实现缩放的功能了,缩放的内存大小是实际的1/(samplesize^2)。但这里还有一个问题,就是实际解析图片的时候是从硬盘上读取的,当图片较大的时候这个解析时间是不确定的,如果直接在UI线程中执行,会观察到明显的停顿,再时间长一点就ANR了,所以需要将图片解析的过程放在异步操作了,可以单开一个线程,也可以使用系统提供的异步任务类AsyncTask,示例如下:

[java]  view plain copy print ?
  1. class BitmapWorkerTask extends AsyncTask<String, Void, Bitmap> {  
  2.     private final WeakReference<ImageView> imageViewReference;  
  3.     private String data = null;  
  4.   
  5.     public BitmapWorkerTask(ImageView imageView) {  
  6.         // Use a WeakReference to ensure the ImageView can be garbage collected  
  7.         imageViewReference = new WeakReference<ImageView>(imageView);  
  8.     }  
  9.   
  10.     // Decode image in background.  
  11.     @Override  
  12.     protected Bitmap doInBackground(String... params) {  
  13.         data = params[0];  
  14.         return decodeSampledBitmapFromFile(data, 100100));  
  15.     }  
  16.   
  17.     // Once complete, see if ImageView is still around and set bitmap.  
  18.     @Override  
  19.     protected void onPostExecute(Bitmap bitmap) {  
  20.         if (imageViewReference != null && bitmap != null) {  
  21.             final ImageView imageView = imageViewReference.get();  
  22.             if (imageView != null) {  
  23.                 imageView.setImageBitmap(bitmap);  
  24.             }  
  25.         }  
  26.     }  
  27. }  

这里需要传入ImageView,当后台图片解析完成后就会将图片加载进行显示。

关于Bitmap图片的加载Google官网上有详细的教程讲解,除了解析还有缓存的解决方案

http://developer.android.com/intl/zh-CN/training/displaying-bitmaps/index.html

   这里主要介绍了使用BitmapFactory.Option来对图片进行缩放。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值