美文网首页
KingFisher SessionManager core l

KingFisher SessionManager core l

作者: 狼性刀锋 | 来源:发表于2018-09-07 15:24 被阅读4次
    
        func tryToRetrieveImageFromCache(forKey key: String,
                                           with url: URL,
                                  retrieveImageTask: RetrieveImageTask,
                                      progressBlock: DownloadProgressBlock?,
                                  completionHandler: CompletionHandler?,
                                            options: KingfisherOptionsInfo)
        {
    
            let diskTaskCompletionHandler: CompletionHandler = { (image, error, cacheType, imageURL) -> Void in
                completionHandler?(image, error, cacheType, imageURL)
            }
            
            func handleNoCache() {
                if options.onlyFromCache {
                    let error = NSError(domain: KingfisherErrorDomain, code: KingfisherError.notCached.rawValue, userInfo: nil)
                    diskTaskCompletionHandler(nil, error, .none, url)
                    return
                }
                self.downloadAndCacheImage(
                    with: url,
                    forKey: key,
                    retrieveImageTask: retrieveImageTask,
                    progressBlock: progressBlock,
                    completionHandler: diskTaskCompletionHandler,
                    options: options)
                
            }
            
            let targetCache = options.targetCache
            // First, try to get the exactly image from cache
            targetCache.retrieveImage(forKey: key, options: options) { image, cacheType in
                // If found, we could finish now.
                if image != nil {
                    diskTaskCompletionHandler(image, nil, cacheType, url)
                    return
                }
                
                // If not found, and we are using a default processor, download it!
                let processor = options.processor
                guard processor != DefaultImageProcessor.default else {
                    handleNoCache()
                    return
                }
                
                // If processor is not the default one, we have a chance to check whether
                // the original image is already in cache.
                let originalCache = options.originalCache
                let optionsWithoutProcessor = options.removeAllMatchesIgnoringAssociatedValue(.processor(processor))
                originalCache.retrieveImage(forKey: key, options: optionsWithoutProcessor) { image, cacheType in
                    // If we found the original image, there is no need to download it again.
                    // We could just apply processor to it now.
                    guard let image = image else {
                        handleNoCache()
                        return
                    }
                    
                    guard let processedImage = processor.process(item: .image(image), options: options) else {
                        diskTaskCompletionHandler(nil, nil, .none, url)
                        return
                    }
                    targetCache.store(processedImage,
                                      original: nil,
                                      forKey: key,
                                      processorIdentifier:options.processor.identifier,
                                      cacheSerializer: options.cacheSerializer,
                                      toDisk: !options.cacheMemoryOnly,
                                      completionHandler: {
                                        guard options.waitForCache else { return }
                                        
                                        let cacheType = targetCache.imageCachedType(forKey: key, processorIdentifier: options.processor.identifier)
                                        diskTaskCompletionHandler(processedImage, nil, cacheType, url)
                    })
                    
                    if options.waitForCache == false {
                        diskTaskCompletionHandler(processedImage, nil, .none, url)
                    }
                }
            }
        }
    
    
    

    这段代码比较简单,就是检索缓存,没有缓存,就尝试下载,值得注意的是这里有可能检索2次缓存, 第一次检索processor缓存,也就是检索加工过的图片,第二次检索原图,这里的逻辑就是缓存可能存储了原图,但是没有存储加工过的图片,这样的话如果能检索到原图,只需要要加工下原图,并缓存下来,这样做的目的可以有效避免重复的网络请求,减少不必要的流量。

        @discardableResult
        func downloadAndCacheImage(with url: URL,
                                 forKey key: String,
                          retrieveImageTask: RetrieveImageTask,
                              progressBlock: DownloadProgressBlock?,
                          completionHandler: CompletionHandler?,
                                    options: KingfisherOptionsInfo) -> RetrieveImageDownloadTask?
        {
            let downloader = options.downloader
            return downloader.downloadImage(with: url, retrieveImageTask: retrieveImageTask, options: options,
                progressBlock: { receivedSize, totalSize in
                    progressBlock?(receivedSize, totalSize)
                },
                completionHandler: { image, error, imageURL, originalData in
    
                    let targetCache = options.targetCache
                    if let error = error, error.code == KingfisherError.notModified.rawValue {
                        // Not modified. Try to find the image from cache.
                        // (The image should be in cache. It should be guaranteed by the framework users.)
                        targetCache.retrieveImage(forKey: key, options: options, completionHandler: { (cacheImage, cacheType) -> Void in
                            completionHandler?(cacheImage, nil, cacheType, url)
                        })
                        return
                    }
                    
                    if let image = image, let originalData = originalData {
                        targetCache.store(image,
                                          original: originalData,
                                          forKey: key,
                                          processorIdentifier:options.processor.identifier,
                                          cacheSerializer: options.cacheSerializer,
                                          toDisk: !options.cacheMemoryOnly,
                                          completionHandler: {
                                            guard options.waitForCache else { return }
                                            
                                            let cacheType = targetCache.imageCachedType(forKey: key, processorIdentifier: options.processor.identifier)
                                            completionHandler?(image, nil, cacheType, url)
                        })
                        
                        // 原图 ??
                        // TODO: 003 completionHandler 为什么等于nil
                        if options.cacheOriginalImage && options.processor != DefaultImageProcessor.default {
                            let originalCache = options.originalCache
                            let defaultProcessor = DefaultImageProcessor.default
                            if let originalImage = defaultProcessor.process(item: .data(originalData), options: options) {
                                originalCache.store(originalImage,
                                                  original: originalData,
                                                  forKey: key,
                                                  processorIdentifier: defaultProcessor.identifier,
                                                  cacheSerializer: options.cacheSerializer,
                                                  toDisk: !options.cacheMemoryOnly,
                                                  completionHandler: nil)
                            }
                        }
                    }
    
                    if options.waitForCache == false {
                        completionHandler?(image, error, .none, url)
                    }
                })
        }
        
    

    这段逻辑比较confuse,要结合上下文来看,主要是store逻辑有点confuse,store的时候,把image和originalData一起传进去,而事实上最终存储的是image这个实参,这里的image在回调之前,已经经过process,和modify了, 所以如果是processor的话,直接存储这个image, 如果用户与此同时要求存储原图的话,那么使用DefaultImageProcessor 序列化 originalData,得到原图image,然后再存储该image.

    相关文章

      网友评论

          本文标题:KingFisher SessionManager core l

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