在Android中高效的加载大图的方法示例

 更新时间:2018年06月05日 14:19:30   转载 作者:ronaldong  
本篇文章主要介绍了在Android中高效的加载大图的方法示例,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

将大图加载到内存中总是令人痛苦,因为我们经常会在应用的崩溃报告中看到OOM(Out Of Memory)的bug。大家都知道,Android系统的内存有限。我们必须牢记这一点。

stackoverflow上有很多关于大图加载的问题,当你的应用程序遇到OOM的时候,你可以选择直接复制粘贴其中的答案来解决这个问题。因此,你完全可以略过本篇文章,但我想介绍一些加载大图的基础知识及其实际工作的原理。

我只想解释图片解码背后的逻辑。我建议你使用Picasso或Glide来加载图片。没有必要重新发明轮子。

将图片加载到内存中

这很简单。你只需要使用BitmapFactory来解码你的图片。

Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.hqimage);
imageView.setImageBitmap(bitmap);

看起来一切正常。但是我要告诉你一个问题,让我们看看这张解码过的图片在内存中实际占据的空间大小。

bitmap.getByteCount()方法将返回bitmap的大小。 这张图片在内存中的大小为12262248字节,相当于12.3 MB。是的,你可能会感到困惑。因为这张图片在磁盘上的实际大小约为3.5 MB,而getByteCount()方法返回的值远大于它。原因如下:

存储在磁盘上的图片是被压缩过的(以JPG,PNG或类似的格式存储)。 一旦将图片加载到内存中,它就不再被压缩,并占用尽可能多的图片的所有像素所需的内存空间。

加载大图的步骤

  1. 获取图片的宽和高
  2. 根据图片的宽和高计算缩放比
  3. 使用压缩比将图片加载到内存中。

BitmapFactory.Options

BitmapFactory可以为我们提供图片的元数据。我们可以使用这个类来实现第一步。

BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeResource(getResources(), R.mipmap.hqimage, options);

我们将BitmapFactory.Options实例传递给BitmapFactory.decodeSource()方法。 options.inJustDecodeBounds = true 是什么意思?这句代码是指我们不想将图片加载到内存中。我们只想获取图片的相关信息(宽度,高度等),并使用这些信息来计算缩放比例。

我们运行这段代码和并打印图片的信息:

options.outHeight : 1126
options.outWidth : 2000
options.bitmap : null

它只输出了图片的高度和宽度。

Reducing Image Size (In Memory)

现在我们需要计算 inSampleSize 。什么是inSampleSize? inSampleSize是BitmapFactory.Options类的一个属性,用于设置图片的缩放比。

如果我们有一张尺寸为1000x1000的图片,并且在解码之前设置inSampleSize的值为2, 那么解码之后,我们将得到一张尺寸为500x500的图片。 如果我们有一张尺寸为200x400的图片,并且在解码之前设置inSampleSize的值为5, 那么解码之后,我们将得到一张尺寸为40x80的图片。

BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
options.inSampleSize = 3; 
BitmapFactory.decodeResource(getResources(), R.mipmap.hqimage, options);

我们可以直接这样做吗?不能,因为我们不知道图片大小是多少。如果它是小图片,并且我们使其更小,那么我们的用户可以看到的就是一些像素而不是图像。有一些图片需要缩放5倍,另一些图片则需要缩放2倍。我们不能将缩放比设置为一个常数,所以我们必须根据图片的大小来计算它的值。

如何计算inSampleSize的值取决于您。我的意思是,你可以根据你的需要编写inSampleSize的计算方法。在android官方文档中,计算结果是2的幂次方。

options.inSampleSize = calculateInSampleSize(options, 500,500);
options.inJustDecodeBounds = false;
Bitmap smallBitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.hqimage, options);

这里我们将 inJustDecodeBounds 的值设为false,并获得了一个bitmap对象。现在,bitmap.getByteCount()方法返回的图片大小是3.1 MB。这是它在内存中的大小。正如我之前说过的,图片存储在磁盘上时会被压缩。当我们将它们加载到内存中时它们会占据更大的内存空间。通过上面这种方法,我们将它在内存中占据的空间大小从12.3 MB减少到了3.1 MB,减少了75%。

Reducing Image Size (In Disk)

我们还可以使用Bitmap的 compress 方法对磁盘上的图片进行压缩。

我们来看看在不改变图片质量的情况下图片被压缩后的大小。 100 表示与原图保持相同的质量。

ByteArrayOutputStream bos = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, bos);
byte[] bitmapdata = bos.toByteArray();

通过计算得到图片在磁盘上的大小为1.6 MB。

我们把compress方法中的质量参数改为50,并再次计算图片大小。

bitmap.compress(Bitmap.CompressFormat.JPEG, 50, bos);

通过计算得到图片在磁盘上的大小为24.4 KB。

注意:在改变compress方法中的质量参数的时候,压缩格式应该是.JPEG。设置为PNG格式的时候,修改是无效的。

下面是一张对比效果图:


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

相关文章

  • Android中TabLayout结合ViewPager实现页面切换效果

    Android中TabLayout结合ViewPager实现页面切换效果

    这篇文章主要介绍了Android中TabLayout结合ViewPager实现页面切换效果,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2016-10-10
  • Android中Binder详细学习心得

    Android中Binder详细学习心得

    这篇文章主要介绍了Android中Binder详细学习心得,并分析了Binder的详细用法,需要的朋友参考下吧。
    2018-01-01
  • adb wireless进行Android手机调试详解

    adb wireless进行Android手机调试详解

    这篇文章给大家讲解了在Android手机上使用adb wireless进行调试的步骤以及问题解决办法,有需要的跟着学习下吧。
    2017-12-12
  • 总结Android App内存优化之图片优化

    总结Android App内存优化之图片优化

    网上有很多大拿分享的关于Android性能优化的文章,主要是通过各种工具分析,使用合理的技巧优化APP的体验,提升APP的流畅度,但关于内存优化的文章很少有看到。下面是我在实践过程中使用的一些方法,很多都是不太成熟的项目,只是将其作为一种处理方式分享给大家。
    2016-08-08
  • Andorid开发之Picasso通过URL获取用户头像的圆形显示

    Andorid开发之Picasso通过URL获取用户头像的圆形显示

    这篇文章主要介绍了Andorid开发之Picasso通过URL获取用户头像的圆形显示,非常不错,具有参考借鉴价值,需要的朋友可以参考下
    2017-06-06
  • 详解Android App中使用VideoView来实现视频播放的方法

    详解Android App中使用VideoView来实现视频播放的方法

    这篇文章主要介绍了Android App中使用VideoView来实现视频播放的方法,举例讲解了VideoView组件中setVidePath(String path)和setVideoURI(Uri uri)的用法,需要的朋友可以参考下
    2016-04-04
  • 你该知道的Gradle配置知识总结

    你该知道的Gradle配置知识总结

    这篇文章主要给大家介绍了关于Gradle配置的相关资料,文中通过示例代码介绍的非常详细,对各位Android开发者们具有一定的参考学习价值,需要的朋友可以参考学习,下面随着小编来一起学习学习吧。
    2017-10-10
  • Android启动引导页使用ViewPager实现

    Android启动引导页使用ViewPager实现

    这篇文章主要为大家详细介绍了Android使用ViewPager实现第一次启动引导页,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2016-07-07
  • Android使用DrawerLayout实现侧滑菜单效果

    Android使用DrawerLayout实现侧滑菜单效果

    这篇文章主要为大家详细介绍了Android使用DrawerLayout实现侧滑菜单效果,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-08-08
  • Android App中使用ViewPager+Fragment实现滑动切换效果

    Android App中使用ViewPager+Fragment实现滑动切换效果

    这篇文章主要介绍了Android App中使用ViewPager+Fragment实现滑动切换效果的方法,借助Fragment可以使Activity的内部管理逻辑更加清晰,需要的朋友可以参考下
    2016-03-03

最新评论