自己实现一个Android网络图片加载器

在Android开发中,我们经常会用到各种各样的图片加载框架来帮助我们加载网络图片,那有没有想过自己实现一个呢

本文记录了实现一个图片框架的整个流程,以及对代码的优化整理过程,文章比较长,如果只对其中的一部分感兴趣直接跳转到相应部分即可

提问环节

把大象装进冰箱分几步?是不是感觉在这初秋时节更加凉爽了呢

好吧,下面开始提问

  • 大多数图片都是网络获取的,如何加载网络图片到本地imageview
  • 图片有可能很大,怎么在加载前进行压缩
  • 每次加载同一个url的图片都要请求网络,可以做一个缓存来防止过度请求吗
  • 头像想显示圆角,怎么通过加载器显示圆角图片
  • 在图片没加载出来之前,会显示placeholder图,加载完成之后切换会闪烁一下,很不美观,怎么处理
  • 写好了代码,但是用起来很麻烦,想用设计模式优化一下,让它用起来像glide一样,减少学习成本,该怎么做

如果只想看其中某一部分,可以直接跳转到相应段落,完整的代码放到了我github上,点击这里可以直达

那么,女士们先生们,下面就开始我们的旅程吧

如何加载网络图片到本地imageview

这个功能很简单,怎么实现我不管,明天上线

这个问题确实很简单,开启一个线程,从网络请求中获取图片流,再组装成bitmap,加载到imageview里面去就行了,看代码

怎么在加载前进行压缩

网络图片有时候会很大,我们的ImageView就那么小一点,图片很大浪费了我们宝贵的内存资源,怎么办呢?我们勤劳的劳动人民有很多办法,没错,就是图片压缩,在加载前我们先获取到图片的宽高以及ImageView的宽高,根据比例来压缩图片,再加载,就没问题啦。

关键利用了
– val options = BitmapFactory.Options()这个Options里有个方法,叫inSampleSize,设置比例

  • 还有一个参数,叫inJustDecodeBounds,只返回图片尺寸

这俩配合,就能让我们压缩图片了

关键代码:

看完了关键代码,是不是很简单呢,我们来看看完整的代码

这个功能稍微复杂一点点,不过也挺简单,相信大家都表示问题不大

可以做一个缓存来防止过度请求吗

当然可以,这个功能也非常简单,我们用文件来进行缓存,怎么确保缓存唯一呢——使用图片url来当文件名即可

这个功能太简单了,直接看代码吧

这个就不用多解释了吧,只是一个文件存取而已

怎么通过加载器显示圆角图片

现在我们的图片加载器以及初具雏形了,但是好多头像都有圆角,我们怎么给这个加载器添加这个功能呢?

这个稍微复杂一点,需要用到canvas的绘制功能,大体思路是这样的
– 绘制一个圆角的rect
– 设置xfermode为PorterDuffXfermode(PorterDuff.Mode.SRC_IN)
– 绘制bitmap
上代码

圆角功能也就完成了

在图片没加载出来之前,会显示placeholder图,加载完成之后切换会闪烁一下,很不美观,怎么处理

一句话,用动画

怎么用动画,这里就要引入一个类,drawable,想必大家都不陌生,我们直接自定义一个drawable,在里面执行显示内容的切换动画即可

看代码

用这个类替代bitmap,即可实现从一个图片到另一个图片的动画效果切换,是不是很简单呢

写好了代码,但是用起来很麻烦,想用设计模式优化一下,让它用起来像glide一样,减少学习成本,该怎么做

核心,使用builder模式

关于这个问题,我们就要去看看glide是怎么做的了

经过对glide的分析,我们发现它是用了builder模式,我们也整一个,我们还发现它的builder不直接设置加载器,而是设置了一个param类,最后加载的时候再传入参数,所以我们也这么玩

下面是我们的builder代码

是不是so easy呢

我们来看看具体使用的时候长什么样

是不是感觉和glide一模一样呢

最后

前面说了那么多,可能有人想说,你的加载图片代码呢,不急,这里就放出全部的代码

至此,我们的图片加载工具已经做好啦,大家可以根据自己的需求愉快的使用了,希望这篇文章能对你有帮助,我们下次再见

u3coding
A software developer

Leave a Comment

Your email address will not be published. Required fields are marked *

*

This site uses Akismet to reduce spam. Learn how your comment data is processed.