美文网首页
Kingfisher about ImageCache

Kingfisher about ImageCache

作者: 狼性刀锋 | 来源:发表于2018-09-07 15:23 被阅读2次
  1. base NSCache store image
  2. base a serialize queue async to access Disk
  3. CachePath: default cache/cacheName

init method

parameters

  • name: CacheName
  • path: Cache path
  • diskCachePathClosure: Cache path append closure,

store and remove Image

  • store Image: sync add image to NSCache and async write imageData to disk if necessary
  • remove Image: sync remove image to NSCache and async remove imageData to disk if necessary

retrieve Image

sync retrieve

retrieveImageInMemoryCache:forKey:options:
retrieveImageInDiskCache:forKey:options:

async retrieve

retrieveImageforKey:options:completionHandler:

clear

auto clear expired Files

when UIApplicationWillTerminate triger cleanExpiredDiskCache
when UIApplicationDidEnterBackground triger backgroundCleanExpiredDiskCache
when UIApplicationDidReceiveMemoryWarning triger clearMemoryCache

manauage clear expired Files

  1. clearDiskCache
  2. clearMemoryCache

clearMemoryCache: just remove Memory Cache
cleanExpiredDiskCache: 清空过期文件
clearDiskCache: 清空所有缓存文件

cleanExpiredDiskCache 代码片段:

  // description remove Expired files
  ...
   if currentDiskCachaSize < maxDiskCacheSize {
    sort disk Cache files by descending
    while  currentDiskCachaSize > maxDiskCacheSize / 2 {
        remove the bigges file 
        }
    
   }

这个地方就很有意思, 作者在清除掉所有已过期文件后,会对当前缓存大小进行再次检测,如果缓存大小超过预期的话,对缓存文件进行降序排序,并不断删除最大的那个文件,直到
当前缓存大小小于预期缓存的1/2。 首先 cleanExpiredDiskCache是能自动触发的,这样的操作能保证缓存文件一直小于预期值,不用用户手动操作,一旦达到临界值直接将缓存减少为预期值的1/2之一,这样可以避免重复触发这个机制, 同时从最大文件开始删除,可以理解为一种删除策略,这样做的目的删除文件同时,尽量减少对用户使用的影响。这种策略不一定是最好的,但应该说是有效的。

    @objc public func backgroundCleanExpiredDiskCache() {
        // if 'sharedApplication()' is unavailable, then return
        guard let sharedApplication = Kingfisher<UIApplication>.shared else { return }

        func endBackgroundTask(_ task: inout UIBackgroundTaskIdentifier) {
            sharedApplication.endBackgroundTask(task)
            task = UIBackgroundTaskInvalid
        }
        
        var backgroundTask: UIBackgroundTaskIdentifier!
        backgroundTask = sharedApplication.beginBackgroundTask {
            endBackgroundTask(&backgroundTask!)
        }
        
        cleanExpiredDiskCache {
            endBackgroundTask(&backgroundTask!)
        }
    }

backgroundCleanExpiredDiskCache 特殊性在于程序在后台不能一直执行,所以必须设置endBackgroundTask来结束线程。

travel image

通过imageKey 检索文件,通常imageKey由URL和其他相关实例id拼接而成

notification

post notification

KingfisherDidCleanDiskCache:

observer notification

UIApplicationDidReceiveMemoryWarning -> clearMemoryCache
UIApplicationWillTerminate -> cleanExpiredDiskCache
UIApplicationDidEnterBackground -> backgroundCleanExpiredDiskCache

技巧解析

/*
  open func retrieveImage(forKey key: String,
                               options: KingfisherOptionsInfo?,
                     completionHandler: ((Image?, CacheType) -> Void)?) -> RetrieveImageDiskTask?
                     */
...
  var sSelf: ImageCache! = self
            block = DispatchWorkItem(block: {
                // Begin to load image from disk
                if let image = sSelf.retrieveImageInDiskCache(forKey: key, options: options) {
                    if options.backgroundDecode {
                        sSelf.processQueue.async {

                            let result = image.kf.decoded
                            
                            sSelf.store(result,
                                        forKey: key,
                                        processorIdentifier: options.processor.identifier,
                                        cacheSerializer: options.cacheSerializer,
                                        toDisk: false,
                                        completionHandler: nil)
                            options.callbackDispatchQueue.safeAsync {
                                completionHandler(imageModifier.modify(result), .memory)
                                sSelf = nil
                            }
                        }
                    } else {
                      ...
                    }


  1. 相对于引用weakSelf,再转StrongSelf这种操作,这里延长了self的生命周期, weakSelf在回调完成的时候,很有可能是nil,那么接下来的操作无法完成,这里进行强引用保证其不为空,确保接下来的操作能够顺利完成
  2. 使用隐式解析,明确告诉编译器,由程序员保证其值的可选性,可以使代码变得简洁,但是不建议大范围的使用,在某些特定的场景还是比较合适的。

相关文章

网友评论

      本文标题:Kingfisher about ImageCache

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