美文网首页扣丁学堂Android培训
扣丁学堂Android培训在Android中高效的加载大图的方法

扣丁学堂Android培训在Android中高效的加载大图的方法

作者: 994d14631d16 | 来源:发表于2018-06-26 17:02 被阅读0次

    将大图加载到内存中总是令人痛苦,因为我们经常会在应用的崩溃报告中看到OOM(OutOfMemory)的bug。大家都知道,Android系统的内存有限。我们必须牢记这一点。所以,当我们进行Android培训时,讲师一般都会将一些细节的地讲解,去放大,去加深,为了以后不要在一些细节的地方,去胡乱找错,结下来就是Android高效加载大图的事例。

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

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

    将图片加载到内存中

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

    Bitmapbitmap=BitmapFactory.decodeResource(getResources(),R.mipmap.hqimage);

    imageView.setImageBitmap(bitmap);

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

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

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

    加载大图的步骤

    获取图片的宽和高

    根据图片的宽和高计算缩放比

    使用压缩比将图片加载到内存中。

    BitmapFactory.Options

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

    BitmapFactory.Optionsoptions=newBitmapFactory.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

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

    ReducingImageSize(InMemory)

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

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

    BitmapFactory.Optionsoptions=newBitmapFactory.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;

    BitmapsmallBitmap=BitmapFactory.decodeResource(getResources(),R.mipmap.hqimage,options);

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

    ReducingImageSize(InDisk)

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

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

    ByteArrayOutputStreambos=newByteArrayOutputStream();

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

    byte[]bitmapdata=bos.toByteArray();

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

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

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

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

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

    下面是一张对比效果图:

    以上就是在Android中高效的加载大图的方法示例,假如你对Android 感兴趣,假如你x想了解更多的有关Android知识,请登录扣丁学堂官网,或者关注微信公众号,了解更多,更有大量Android在线视频教程。心动不如行动!

    相关文章

      网友评论

        本文标题:扣丁学堂Android培训在Android中高效的加载大图的方法

        本文链接:https://www.haomeiwen.com/subject/rnymyftx.html