在网上看了不少文章,发现还是官方文档介绍最详细,把重要的东西简单摘要出来。详细可看官方文档地址 ( 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. 解决Class 'swoole_server' not found

    1.看下cli模式是否可以正常工作,命令行下运行 php -r "echo php_sapi_name();" 这条命令就是在cli模式运行php语句,php -r就是run一条p ...

  2. 【BZOJ4009】[HNOI2015]接水果 DFS序+整体二分+扫描线+树状数组

    [BZOJ4009][HNOI2015]接水果 Description 风见幽香非常喜欢玩一个叫做 osu!的游戏,其中她最喜欢玩的模式就是接水果.由于她已经DT FC 了The big black, ...

  3. G - 湫湫系列故事——减肥记I

    G - 湫湫系列故事——减肥记I Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u De ...

  4. vue组件父子组件之间传递数据

    举个栗子: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF ...

  5. 【python】-- 装饰器、迭代器、生成器

    装饰器 装饰器本质是函数,是用来装饰其他函数,顾名思义就是,为其他的函数添加附件功能的. 一.装饰器原则: 不能修改被装饰函数的源代码 不能修改被装饰函数的调用方式 def logging(): pr ...

  6. 【译】Java语言速览:StackOverflow

    Java (请不要与 JavaScript 搞混) 是一种设计为与 Java 虚拟机 (JVM) 一起使用的多用途编程语言.一般称呼安装了相关工具使其可以开发并运行 Java 程序的电脑系统为 &qu ...

  7. Android系统字体规范

    我们在做Android移动APP设计的时候,字号的选择也是很让人头疼,转载一份有关Android系统字体规范,如果在做Android项目的用户应该看看,如果有任何建议欢迎在留言处与我们交流探讨. 主要 ...

  8. BAPI_SALESORDER_CREATEFROMDAT2 创建退货SO

    BAPI_SALESORDER_CREATEFROMDAT2创建退货订单时,会出现以下错误:不允许业务对象 BUS2032 和销售凭证类别 H 的组合. 解决办法: 采用/原BAPI的内嵌BAPI: ...

  9. eclipse InvocationTargetException 错误解决

    1.今天做一个推送的,用到了几个jar包,直接以User Library的形式加进 在单元测试中,测试的很好,没有任何问题, 但是在action中测试,一测试就崩. 跟踪以后出现InvocationT ...

  10. GIT笔记:GITHUB教程【官方自译版】

    GIT笔记:将项目发布到GITHUB GITHUB是什么 GitHub是版本控制和协作的代码托管平台.它可以让你和其他人在任何地方一起工作. 1.创建一个新的仓库 存储库通常用于组织单个项目.存储库可 ...