Glide是一款优秀的图片加载框架,简单的配置便可以使用起来,为开发者省下了很多的功夫。不过,它没有提供其加载图片进度的api,对于这样的需求,实现起来还真颇费一番周折。

尝试

遇到这个需求,第一反应是网上肯定有人实现过,不妨借鉴一下别人的经验。

Glide加载图片实现进度条效果

可惜,这个实现是基于3.7版本的,4.0版本以上的glide改动比较大,using函数已经被移除了

using()
The using() API was removed in Glide 4 to encourage users to register their components once with a AppGlideModule to avoid object re-use. Rather than creating a new ModelLoader each time you load an image, you register it once in an AppGlideModule and let Glide inspect your model (the object you pass to load()) to figure out when to use your registered ModelLoader.
To make sure you only use your ModelLoader for certain models, implement handles() as shown above to inspect each model and return true only if your ModelLoader should be used.

思考

又要用最新的版本又希望给其增加功能,鱼与熊掌不可兼得?“贪新厌旧”的我怎会轻易放弃。我对加载图片进度的需求再理了一遍,发现可以用其他思路简化一下:

代码如下:

OkHttpStreamFetcher.this.stream = ContentLengthInputStream.obtain(OkHttpStreamFetcher.this.responseBody.byteStream(), contentLength);

ContentLengthInputStream是glide的工具类,用来读取输入流的,点进去看看,发现有几个read方法

  public synchronized int read() throws IOException {
    int value = super.read();
    this.checkReadSoFarOrThrow(value >= 0?1:-1);
    return value;
  }

  public int read(byte[] buffer) throws IOException {
    return this.read(buffer, 0, buffer.length);
  }

  public synchronized int read(byte[] buffer, int byteOffset, int byteCount) throws IOException {
    return this.checkReadSoFarOrThrow(super.read(buffer, byteOffset, byteCount));
  }

所以,我的解决方法就是在这里计算下载进度和进行进度的报告的,把这个类从源码里拷贝出来,替换掉OkHttp模块里面的ContentLengthInputStream,并在这插入自己的下载进度逻辑就行了。

具体的代码实现就不贴出来了,写个大概的思路:

下载图片的时候传入图片进度监听,用集合容器,例如map保存监听的实例,key为url,下载过程中计算下载进度后通过url找到对应的回调返回进度,图片加载完毕后将回调从集合了移除(glide提供了图片加载完毕的回调)。

ok,就这样,有不合理的地方欢迎指出,又更好更优雅的实现方式请不吝指教。也希望大家多多支持脚本之家。

02-06 15:00