Android 框架练成 教你打造高效的图片加载框架

820 查看

1、概述

优秀的图片加载框架不要太多,什么UIL , Volley ,Picasso,Imageloader等等。但是作为一名合格的程序猿,必须懂其中的实现原理,于是乎,今天我就带大家一起来设计一个加载网络、本地的图片框架。有人可能会说,自己写会不会很渣,运行效率,内存溢出神马的。放心,我们拿demo说话,拼得就是速度,奏事这么任性。

好了,如果你看过之前的博文,类似Android Handler 异步消息处理机制的妙用 创建强大的图片加载类,可能会对接下来文章理解会有很大的帮助。没有的话,就跟我往下继续走吧,也不要去看了。

关于加载本地图片,当然了,我手机图片比较少,7000来张:

1、首先肯定不能内存溢出,但是尼玛现在像素那么高,怎么才能保证呢?我相信利用LruCache统一管理你的图片是个不二的选择,所有的图片从LruCache里面取,保证所有的图片的内存不会超过预设的空间。

2、加载速度要刚刚的,我一用力,滑动到3000张的位置,你要是还在从第一张给我加载,尼玛,你以为我打dota呢。所以我们需要引入加载策略,我们不能FIFO,我们选择LIFO,当前呈现给用户的,最新加载;当前未呈现的,选择加载。

3、使用方便。一般图片都会使用GridView作为控件,在getView里面进行图片加载,当然了为了不错乱,可能还需要用户去自己setTag,自己写回调设置图片。当然了,我们不需要这么麻烦,一句话IoadImage(imageview,path)即可,剩下的请交给我们的图片加载框架处理。

做到以上几点,关于本地的图片加载应该就木有什么问题了。

关于加载网络图片,其实原理差不多,就多了个是否启用硬盘缓存的选项,如果启用了,加载时,先从内存中查找,然后从硬盘上找,最后去网络下载。下载完成后,别忘了写入硬盘,加入内存缓存。如果没有启用,那么就直接从网络压缩获取,加入内存即可。

2、效果图

终于扯完了,接下来,简单看个效果图,关于加载本地图片的效果图:可以从Android 超高仿微信图片选择器 图片该这么加载这篇博客中下载Demo运行。

下面演示一个网络加载图片的例子:

80多张从网络加载的图片,可以看到我直接拖到最后,基本是呈现在用户眼前的最先加载,要是从第一张到80多,估计也是醉了。

此外:图片来自老郭的博客,感谢!!!ps:如果你觉得图片不劲爆,Day Day Up找老郭去。

3、完全解析

1、关于图片的压缩

不管是从网络还是本地的图片,加载都需要进行压缩,然后显示:

用户要你压缩显示,会给我们什么?一个imageview,一个path,我们的职责就是压缩完成后显示上去。

1、本地图片的压缩

a、获得imageview想要显示的大小

想要压缩,我们第一步应该是获得imageview想要显示的大小,没大小肯定没办法压缩?

那么如何获得imageview想要显示的大小呢?

可以看到,我们拿到imageview以后:

首先企图通过getWidth获取显示的宽;有些时候,这个getWidth返回的是0;

那么我们再去看看它有没有在布局文件中书写宽;

如果布局文件中也没有精确值,那么我们再去看看它有没有设置最大值;

如果最大值也没设置,那么我们只有拿出我们的终极方案,使用我们的屏幕宽度;

总之,不能让它任性,我们一定要拿到一个合适的显示值。

可以看到这里或者最大宽度,我们用的反射,而不是getMaxWidth();维萨呢,因为getMaxWidth竟然要API 16,我也是醉了;为了兼容性,我们采用反射的方案。反射的代码就不贴了。

b、设置合适的inSampleSize

我们获得想要显示的大小,为了什么,还不是为了和图片的真正的宽高做比较,拿到一个合适的inSampleSize,去对图片进行压缩么。

那么首先应该是拿到图片的宽和高:

这三行就成功获取图片真正的宽和高了,存在我们的options里面;

然后我们就可以happy的去计算inSampleSize了: