大图片加载的处理策略

首先这是我第一次发表文章和第一次在网上写文章,写的不好的请见谅。因为我也经常看别人写的博客,所以我觉得在开发中将一些自己学到的记录起来是很好的,别人能学习的到而我自己也能回顾,。接下来就不罗嗦啦,直入我们今天要写的主题中。
接下来我要讲的是我们平时在安卓开发中或者面试中会用到的,大图片加载的处理策略,其实大图片的处理策略有两个核心的API,这里我们以Volley框架加载图片作为例子,贴上核心代码先:
大图片加载的处理策略
文章图片
上面的代码我们运行一下我们会发现,图片加载不成功,看一下Log,这里报了一行错误:
大图片加载的处理策略
文章图片
这里其实报了一个OOM的错误,内存溢出,没错,加载大图的时候内存空间不够会导致内存溢出,。接下来我们把上面的其中两个参数改一下:
ImageRequest(String url, Response.Listener listener,intmaxWidth,intmaxHeight,

ScaleType scaleType, Config decodeConfig, Response.ErrorListener errorListener);
大图片加载的处理策略
文章图片
我们把上面的测试的代码中intmaxWidth,intmaxHeight,这两个属性改为100和100,测试结果如下:
【大图片加载的处理策略】这时我们发现图片加载出来了,这是为什么呢?接下来我们跟踪下源码。
其实Volley在加载图片的时候底层会走一个方法:
大图片加载的处理策略
文章图片
这个方法在IamgeRequest中,其实真正请求网络加载图片的时候会执行这个方法,我们也看到其实这个方法是执行一个网络请求,这里也看到我们刚才所报的错误,就是从这里来的,接下来我们继续跟踪一下‘doParse()这个方法:
大图片加载的处理策略
文章图片
大图片加载的处理策略
文章图片
这里我们关注一行判断: if(mMaxWidth==0&&mMaxHeight==0),我们之前把这些值设置为0,0的时候,就会执行到里面的方法,所以才会报出OOM,那么当我们设置为100,100的时候呢,为什么图片可以加载成功呢,我们对比一下下面的代码可以知道:其实真是多了一个这样子的属性:
这个InJustDecodeBounds参数有什么作用呢?我们毫不客气的点进去看下官方的注释:
大图片加载的处理策略
文章图片
其实官方英文的解释是这样的意思:如果这个值设置为true的话,将会返回一个null,其实也就是会返回一个空的bitmap,但是out属性会被赋值,可以获取到这张图片的宽和高,系统不会为这个Bitmap分配内存。
通过这里我们原来大图片缓存策略之一是要设置这个BitmapFactory.inJustDecodeounds的值为true,我们接着看代码:
大图片加载的处理策略
文章图片
这里我们看到关注底下有一行代码:decodeOptions.inSampleSize = findBestSampleSize(....);
这个inSampleSize有什么作用呢,我们接下里继续点进去看一下:
大图片加载的处理策略
文章图片
看到这一大段英文是不是头晕?不用怕,大概看得懂就行了,SampleSize是采样率的意思,其实官方想表达的意思是,当这个值大于1的时候。。。。。。。。。。中间省略,自己有道,然后举个例子,inSampleSize == 4这个值设置为4的时候,,会返回1/4之一宽和高的图片,也是就是图片会缩放到原来的1/16大小。当这个值小于1的时候他会赋值为1,解码器解码的时候会四舍五入到2的平方,也就是1/4之一。建议设置为2这个值。
然后解释一下这行代码的作用:
大图片加载的处理策略
文章图片
这里通过一个方法将我们之前设置的宽和高,和设置了InJustDecodeBounds == true之后得到的out属性的宽和高,通过一些算法得到压缩过后的采样率。值得一提的是,每个图片加载框架的算法都不同,但核心点都是一样的,这里不过多解释。
最后总结一下:
inJustDecodeBounds: 开关,设置为true的时候,bitmap为null,但是out属性会被赋值,可以获取到这张图片的宽和高,系统不会为这个bitmap分配内存。

通过BitmapFactory的一个inJustDecodeounds获取到图片的out属性:宽和高,但是不会为这张图片分配内存。

BitmapFactory.inSampleSize(采样率)如果设置的值大于1,假如设置为4,宽和高都缩小4分之1,也就是整体缩小16分之1;

大图片的加载核心其实就是两个API,一个是设置bitmap的采样率inSampleSize,设置采样率要获取原图片的宽和高属性,如果直接获取,会加载到内存中,会导致OOM,所以我们需要先设置一个开关,inJustDecodeounds,设置这个值为true,开启bitmap的out属性,获取到宽和高,当时bitmap不会加载到内存中。返回bitmap为空。



到这里,我的博文就结束啦,希望能对你有所帮助,接下来我也会慢慢的更新自己所学到的Android技术,大家共勉之。

    推荐阅读