在网上看了不少文章,发现还是官方文档介绍最详细,把重要的东西简单摘要出来。详细可看官方文档地址 ( http://www.bangchui.org/read.php?tid=9 ) 。


在应用中显示图片,如果不多加小心,很容易就会使应用因为异常“java.lang.OutofMemoryError:bitmap size exceeds VM budget”而导致crash。在android中加载图片需要一定的技巧性,主要是因为:

1.通常设备资源有限,安卓设备给每个应用只分配16M的空间。当然很多设备都为应用设置了更高的内存,下面这个文档的3.7节中有介绍不同屏幕设备应用需要的最小内存(http://source.android.com/compatibility/downloads.html)。

2.图片通常很占内存。例如Galxy Nexus相机分辨率高达2592x1936,如果图片配置为ARGB_8888(2.3以后默认配置),加载一张照片就需要19M内存(2592x1936x4 bytes),会很快消耗完一个应用的内存。

3.安卓的UI中通常需要一下加载多张图片,如ListView,ViewPager。


本文主要介绍怎么高效地加载大图而不至于使你的应用内存溢出。大图通常会比屏幕尺寸大很多,然而加载一个高分辨率的图片并不能带来多少视觉体验,通过下面两步可以加载一个压缩尺寸的图片就节省内存。

第一步,读取图片尺寸和类型。

BitmapFactory类提供了多个decoding方法(decodeByteArray(), decodeFile(), decodeResource(), 等)使可以通过各种数据源创建Bitmap,这些方法会在bitmap构造时申请内存,对于大图,这样会很容易导致内存溢出。每种decode方法都有一个额外的标志参数BitmapFactory.Options,设置它的inJustDecodeBounds属性为true,可以避免decode时分配内存,返回的Bitmap对象是一个null值,但能得到图片的原始高度、宽度和格式(保存在option的outWidth,outHeight,outMimeType中)。通过这种方式,可以在构造图片前获得图片属性。下面是示例代码:


    BitmapFactory.Options options = new BitmapFactory.Options();    options.inJustDecodeBounds = true;    BitmapFactory.decodeResource(getResources(), R.id.myimage, options);    int imageHeight = options.outHeight;    int imageWidth = options.outWidth;    String imageType = options.outMimeType; 

为了避免内存溢出,最好在加载图片前都对尺寸做检查,除非你保证源图片没有大图。

第二步,加载缩小后的图片到内存。

现在知道了原图片的尺寸,根据实际情况决定你要加载它缩小多少倍后的图片。例如你用一个128x96的ImageView显示一张1024x768的原图,根本没有必要把原图读加载到内存。加载一张缩小后的图片到内存,只需要把BitmapFactory.Options对象的inSampleSize设为true,然后给inSampleSize设一个值就行了(可以理解inSampleSize为n,图片就缩小到1/n大小)。

下面是一段加载图片的一段示例代码


  1. public static int calculateInSampleSize(            BitmapFactory.Options options, int reqWidth, int reqHeight) {    // Raw height and width of image    final int height = options.outHeight;    final int width = options.outWidth;    int inSampleSize = 1;    if (height > reqHeight || width > reqWidth) {        if (width > height) {            inSampleSize = Math.round((float)height / (float)reqHeight);        } else {            inSampleSize = Math.round((float)width / (float)reqWidth);        }    }    return inSampleSize;}


    public static Bitmap decodeSampledBitmapFromResource(Resources res, int resId,          int reqWidth, int reqHeight) {        // First decode with inJustDecodeBounds=true to check dimensions      final BitmapFactory.Options options = new BitmapFactory.Options();      options.inJustDecodeBounds = true;      BitmapFactory.decodeResource(res, resId, options);        // Calculate inSampleSize      options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);        // Decode bitmap with inSampleSize set      options.inJustDecodeBounds = false;      return BitmapFactory.decodeResource(res, resId, options);  } 


更多相关文章

  1. Android的底层库libutils介绍
  2. Android用户界面 UI组件--ImageView及其子类ImageButton,QuickCo
  3. 界面编程之基本界面组件(7)ImageView(图像视图)
  4. TextView使用完全讲解
  5. Android属性系统
  6. 华为android 10 手机恢复删除的图片,目前只能恢复小图。
  7. Android开机LOGO
  8. android studio 使用android:drawableTop与**顶部失真
  9. Android:Activity(五):Activity加载模式

随机推荐

  1. 仿写android音乐播放器的问题
  2. Android资源文件简介
  3. Android数据存储--sqlite
  4. Android(安卓)4.1的新特性介绍
  5. Android图片异步加载的实现
  6. [Android] ImageView.ScaleType设置图解
  7. 创业公司招人才
  8. Android中Adapter中edittext,checkbox记住
  9. Android(安卓)SharedPreferences应用解析
  10. android WebView总结