android地图图片加载,Android图片加载解析之Bitmap

写在前面的话,本篇文章是参考自《Android开发艺术探索》所写,看此书已是2015年的事情啦,由于独立开放项目,以至于对于Android原理性东西生疏,最近需要换工作,重新捡起此书,仍有大的收获。故在此留下一笔。(总结是很有必要的)

在Android图片加载方面,我们少不了与Bitmap(位图)打交道,但是与它相处需要步步谨慎啊,稍不留神就跟OOM(内存溢出)见面啦。

> java.lang.OutofMemoryError:bitmap size exceeds VM budget

如何高效地加载Bitmap是我们每一个开发者都不容忽视的问题。

下面我们来逐步地深入探讨这个问题:

一:如何加载Bitmap

Bitmap在Android中简单理解为一张图片,图片的格式可以是(JPEG ,PNG ,WEBP等)。

BitmapFactory为我们提供了4类方法来加载Bitmap:

1.decodeFile();

2.decodeResource();

3.decodeStream();

4.decodeByteArray();

看图更明白一些:

e00dce838fb2

Bitmap加载方式.png

如果深入去查看这些方法,会发现其中** decodeFile()和decodeResource()都间接调用了decodeStream()。这四类加载方法最终都是在Android低层实现的,对应着BitmapFactory类的几个native方法。

到了这里,Bitmap的简单加载就介绍完毕,但是Bitmap的加载远没有结束,因为如果我们这么简单使用,会经常与OOM**邂逅。这就需要进行高效设置啦。

二:如何高效地加载Bitmap

首先来交代一下背景:其实所谓高效,只不过就是不浪费系统那宝贵的资源。在Android开发中,与Bitmap打交道最多的控件要属ImageView。在很多情况下,ImageView都没有图片的原始尺寸那么大,这时如果我们不加任何设置而直接让ImageView来显示图片。Android系统往往都是先将整个图片加载到内存,然后再显示出来。这显然是画蛇添足。

我们可以通过BitmapFactory.Options来通过设置采样率来加载所需尺寸的图片,这样就降低内存占用从而在一定程度上降低了OOM的发生率。BitmapFactory提供的加载图片的四类方法都支持BitmapFactory.Options参数,通过它我们就可以很方便地进行采样缩放。(意不意外,惊不惊喜?)

那么我们是如何通过BitmapFactory.Options来进行采样缩放的呢?

这里主要用到了inSampleSize这个变量;

e00dce838fb2

采样率.png

从图上的注释我们可以知道:

如果inSampleSize > 1,将会给我们返回一个比原图更小的图片来节约内存。举个例子,当设置 inSampleSize = 4时,那么采样后的图片其宽和高都缩小为原图的1/4,而像素数为原图的1/16,这样其所占用的内存也只有原来的1/16。

当 inSampleSize <= 1时,系统都会当成1来对待;

这个inSampleSize 的取值应该总为2 的指数(1,2,4,8,18...),如果外界传递给系统的inSampleSize不为2的指数,则系统会向下取整并选择一个最接近2的指数来代替。

获取采样率的流程:

获取BitmapFactory.Options的对象;

将BitmapFactory.Options的inJustDecodeBounds参数设置为true并加载图片;

从BitmapFactory.Options中取出原始图片的宽高信息,即outWidth和outHeight参数。

根据采样率的规则并结合目标View的所需大小计算采样率inSampleSize。

将BitmapFactory.Options的inJustDecodeBounds参数设置为false,然后重新加载图片。

针对于inJustDecodeBounds这个变量:

将 inJustDecodeBounds参数设置为ture时,BitmapFactory只会解析图片的原始宽高信息,并不会真正地加载图片,所以这个操作是轻量级的。

"Talk is cheap. Show me the code." - Linus Torvalds

// 从res中加载bitmap

public static Bitmap decodeBitmapFromRes(Resources res,int resId,

int requestWidth,

int requestHeight){

BitmapFactory.Options options = new BitmapFactory.Options();

options.inJustDecodeBounds = true;

BitmapFactory.decodeResource(res,resId,options);

//设置采样率

options.inSampleSize = calculateInSampleSize(options,requestWidth,requestHeight);

options.inJustDecodeBounds = false;

return BitmapFactory.decodeResource(res,resId,options);

}

//计算采样率

private static int calculateInSampleSize(BitmapFactory.Options options,

int requestWidth,

int requestHeight) {

int outWidth = options.outWidth;

int outHeight = options.outHeight;

int inSampleSize = 1;

if(outHeight>requestHeight || outWidth > requestWidth){

int halfHeight = outHeight / 2;

int halfWidth = outWidth / 2;

while ((halfHeight/ inSampleSize) >= requestHeight

&& (halfWidth / inSampleSize) >= requestWidth){

inSampleSize *= 2;

}

}

return inSampleSize;

}

到此,Bitmap加载可以在实际开发工作中使用啦。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值