在网上看了不少文章,发现还是官方文档介绍最详细,把重要的东西简单摘要出来。详细可看官方文档地址 ( 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中)。通过这种方式,可以在构造图片前获得图片属性。下面是示例代码:

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

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

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

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

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

  1. public static int calculateInSampleSize(
  2. BitmapFactory.Options options, 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. if (height > reqHeight || width > reqWidth) {
  8. if (width > height) {
  9. inSampleSize = Math.round((float)height / (float)reqHeight);
  10. } else {
  11. inSampleSize = Math.round((float)width / (float)reqWidth);
  12. }
  13. }
  14. return inSampleSize;
  15. }
  1. public static Bitmap decodeSampledBitmapFromResource(Resources res, int resId,
  2. int reqWidth, int reqHeight) {
  3. // First decode with inJustDecodeBounds=true to check dimensions
  4. final BitmapFactory.Options options = new BitmapFactory.Options();
  5. options.inJustDecodeBounds = true;
  6. BitmapFactory.decodeResource(res, resId, options);
  7. // Calculate inSampleSize
  8. options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
  9. // Decode bitmap with inSampleSize set
  10. options.inJustDecodeBounds = false;
  11. return BitmapFactory.decodeResource(res, resId, options);
  12. }

Android中高效的显示图片之一 ——加载大图的更多相关文章

  1. Android中高效的显示图片之二——在非UI线程中处理图片

    在“加载大图”文章中提到的BitmapFactory.decode*方法,如果源数据是在磁盘.网络或其它任何不是在内存中的位置,那么它都不应该在UI线程中执行.因为它的加载时间不可预测且依赖于一系列因 ...

  2. Android中高效的显示图片之三——缓存图片

    加载一张图片到UI相对比较简单,如果一次要加载一组图片,就会变得麻烦很多.像ListView,GridView,ViewPager等控件,需要显示的图片和将要显示的图片数量可能会很大. 为了减少内存使 ...

  3. Android中ViewPager+Fragment取消(禁止)预加载延迟加载(懒加载)问题解决方案

    转载请注明出处:http://blog.csdn.net/linglongxin24/article/details/53205878本文出自[DylanAndroid的博客] Android中Vie ...

  4. Android中使用WebView, WebChromeClient和WebViewClient加载网页 (能够执行js)

    Android中使用WebView, WebChromeClient和WebViewClient加载网页   在android应用中,有时要加载一个网页,如果能配上一个进度条就更好了,而android ...

  5. Android训练课程(Android Training) - 高效的显示图片

    高效的显示图片(Displaying BitmapsEfficiently) 了解如何使用通用的技术来处理和读取位图对象,让您的用户界面(UI)组件是可响应的,并避免超过你的应用程序内存限制的方式.如 ...

  6. Android中自定义ListView实现上拉加载更多和下拉刷新

    ListView是Android中一个功能强大而且很常用的控件,在很多App中都有ListView的下拉刷新数据和上拉加载更多这个功能.这里我就简单记录一下实现过程. 实现这个功能的方法不止一个,Gi ...

  7. Android中使用WebView, WebChromeClient和WebViewClient加载网页

    在android应用中,有时要加载一个网页,如果能配上一个进度条就更好了,而android 中提供了其很好的支持, 其中webView的一系列用法,比如 webView.getSettings().s ...

  8. 前端性能优化成神之路--图片懒加载(lazyload image)

    图片懒加载(当然不仅限于图片,还可以有视频,flash)也是一种优化前端性能的方式.使用懒加载可以想要看图片时才加载图片,而不是一次性加载所有的图片,从而在一定程度从减少服务端的请求 什么是懒加载 懒 ...

  9. Android新浪微博客户端(七)——ListView中的图片异步加载、缓存

    原文出自:方杰|http://fangjie.info/?p=193转载请注明出处 最终效果演示:http://fangjie.sinaapp.com/?page_id=54 该项目代码已经放到git ...

随机推荐

  1. mongodb 指南

    mongodb概述 mongodb安装 mongodb启动参数 mongodb权限体系 mongodb管理命令 mongodb备份恢复

  2. PerconaXtraBackup-2.2.8手册翻译

    1.1.2 Percona Xtrabackup特性 * 不停机创建Innodb数据库热备 * 对Mysql数据库创建增量备份 * 压缩数据流方式备份到异地服务器 * 更加便捷创建新的mysql从库 ...

  3. ios8 一些运行问题

     iOS10相册相机闪退bughttp://www.jianshu.com/p/5085430b029fiOS 10 因苹果健康导致闪退 crashhttp://www.jianshu.com/p/5 ...

  4. Lumen开发:如何向 IoC 容器中添加自己定义的类

    版权声明:本文为博主原创文章,未经博主允许不得转载. 先在起始文件bootstrap/app.php加上$app->register(App\Providers\User\UserService ...

  5. 九度OJ 1187:最小年龄的3个职工 (排序)

    时间限制:1 秒 内存限制:32 兆 特殊判题:否 提交:2291 解决:936 题目描述: 职工有职工号,姓名,年龄.输入n个职工的信息,找出3个年龄最小的职工打印出来. 输入: 输入第一行包括1个 ...

  6. html checkbox的checked属性问题和value属性问题

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  7. HTML-Table-Td固定宽度使内容换行

    table style="TABLE-LAYOUT: fixed;" td style="WORD-WRAP: break-word;WIDTH:200px;"

  8. vim 一键添加注释 自动添加文件头注释

    估计大家也都和我一样用过不少的编辑器,什么notepad2,emeditor,editplus,ultraedit,vs2005,sourceinsight,slickedit,emacs,vim(g ...

  9. 工作中你肯定会有关于 Yii2 的小贴士用法,在下面评论分享出来吧。

    场景: 数据库有user表有个avatar_path字段用来保存用户头像路径 需求: 头像url需要通过域名http://b.com/作为基本url 目标: 提高代码复用 此处http://b.com ...

  10. H5 input默认数字键盘,显示为密码格式

    <P> <span class="yzname w25">银行密码</span> <input class="j_passwor ...