美文网首页程序员
SDWebImage使用时,url未变,但图片资源变化如何及时更

SDWebImage使用时,url未变,但图片资源变化如何及时更

作者: 詹姆斯洪尼古拉斯利 | 来源:发表于2019-04-09 16:00 被阅读0次

    面试官提问频率比较高的一个问题就是:如果同一url对应图片资源已经改变,当使用SDWebImage时该如何处理才能让图片及时刷新内容?

    iOS 9以前,SD未能很好地处理此类问题,需要我们手动修改一下源码,网络上答案满天飞,举个比较常用的处理方法:

    1、发起时这样调用方法

    [self.imageView sd_setImageWithURL:[NSURL URLWithString:urlStr] placeholderImage:nil options:SDWebImageRefreshCached];
    

    2、修改SDWebImage源码,需要找到SDWebImageManager.m, 178行代码处换行并追加代码

     downloaderOptions &= ~SDWebImageDownloaderUseNSURLCache;
    

    用这个方法可以解决如上问题,但为什么呢?下面我们结合新老版本的SDWebImage源码来实实在在的看看到底为什么这么改就可以,根本原因是什么?

    首先要清楚一点,SDWebImage的缓存策略,NSURLCache + SDWebImageCache(也就是SD自己的缓存机制)

    NSURLCache会缓存网络请求结果,一旦某次开启了同样的请求并指定可以返回NSURLCache的缓存内容,那么会直接调用NSURLCache的缓存内容直接返回

    而url对应内容变化,客户端未刷新的原因就在于请求时,不小心指定了使用NSURLCache的优化机制直接返回了内容,却并未发起请求,去获取最新资源

    好了,接下来看源码,我找到的是3.7.6的SDWebImage老代码

    image

    这里是下载任务开启前的操作,一旦指定了options 包含了SDWebImageRefreshCached类型,downloaderOptions会被追加一个SDWebImageDownloaderUseNSURLCache类型,标志着可以启用NSURLCache机制

    然后看下一张图


    image

    下载任务开启前,缓存策略经过一个枚举并运算赋值成了 NSURLRequestUseProtocolCachePolicy

    再看另一张图


    image

    定位到SDWebImageDownloaderOperation.m 文件,可以看到当需要缓存请求返回结果的时候,有一个if逻辑,当指定了对应的属性后才会不缓存本次请求结果

    结合以上三段源码我们就可以得到结论了:

    sd_setImageWithUrl 时,虽然我们指定了SDWebImageRefreshCached操作,但相关逻辑执行后,会启用NSURLCache机制,并在拿到请求结果后被NSURLCache缓存起来,下次有相同请求进来时,会触发NSURLCache机制,返回之前请求的结果,所以,导致url未变,图片资源已变,但客户端展示未刷新问题

    然而,iOS9之后SDWebImage因NSURLConnection被废弃缘故,改用推荐的NSURLSession,在这之后,如果面临url不变,资源改变的情况,再也不需要动手修改源码了,下面我们看看改版后的SD做了什么

    image

    改版后,这处代码做了优化,判断条件修改为除非用户 指定了要启用NSURLCache缓存机制,否则默认情况不允许缓存response,规避掉了相关问题

    但是,这样看上去每一次都会重新开启下载任务去下载啊,岂不是造成了资源浪费。答案是否定的,这里就需要引入网络通信协议相关概念,Http、Https缓存机制中提供了验证机制,利用Last-Modified 或者Entity Tag(ET)来验证当前已缓存的资源是否与服务端最新资源相同。有兴趣的朋友可以去看一下RFC文档

    所以,重写willCacheResponse方法时,虽然不允许缓存请求结果,但是再进行请求时,由于验证机制的存在,仍然避免了相同资源的重复请求

    相关文章

      网友评论

        本文标题:SDWebImage使用时,url未变,但图片资源变化如何及时更

        本文链接:https://www.haomeiwen.com/subject/sbfiiqtx.html