KingFisher 网络请求流程

首先一个 URL 对应一个FetchLoad


    class ImageFetchLoad {
        var contents = [(callback: CallbackPair, options: KingfisherOptionsInfo)]()
        var responseData = NSMutableData()

        var downloadTaskCount = 0
        var downloadTask: RetrieveImageDownloadTask?
        var cancelSemaphore: DispatchSemaphore?
    }

[URL: FetchLoad];

当每次download 的时候 ,先去匹配这个FetchLoad,如果FetchLoad存在且downloadTaskCount != 0的话,就不会发起新的网络请求,

FetchLoad 使用downloadTaskCount 作为task引用计数,也就是说同一个URL的请求,不会造成重复的网络请求,只会造成downloadTaskCount+=1,当请求结束后,
会挨个调用contents中的闭包回调,cancelSemaphore 作为线程同步的信号,用来保证线程安全的,整个流程就是这样。

而在回调的时候,会触发processImage方法,该方法会根据content.options 加工和修改图片。

    private func processImage(for task: URLSessionTask, url: URL) {

        guard let downloader = downloadHolder else {
            return
        }
        
        // We are on main queue when receiving this.
        downloader.processQueue.async {
            
            guard let fetchLoad = downloader.fetchLoad(for: url) else {
                return
            }
            
            self.cleanFetchLoad(for: url)
            
            let data: Data?
            let fetchedData = fetchLoad.responseData as Data
            
            if let delegate = downloader.delegate {
                data = delegate.imageDownloader(downloader, didDownload: fetchedData, for: url)
            } else {
                data = fetchedData
            }
            
            // Cache the processed images. So we do not need to re-process the image if using the same processor.
            // Key is the identifier of processor.
            var imageCache: [String: Image] = [:]
            for content in fetchLoad.contents {
                
                let options = content.options
                let completionHandler = content.callback.completionHandler
                let callbackQueue = options.callbackDispatchQueue
                
                let processor = options.processor
                var image = imageCache[processor.identifier]
                if let data = data, image == nil {
                    image = processor.process(item: .data(data), options: options)
                    // Add the processed image to cache. 
                    // If `image` is nil, nothing will happen (since the key is not existing before).
                    imageCache[processor.identifier] = image
                }
                
                if let image = image {

                    downloader.delegate?.imageDownloader(downloader, didDownload: image, for: url, with: task.response)

                    let imageModifier = options.imageModifier
                    let finalImage = imageModifier.modify(image)

                    if options.backgroundDecode {
                        let decodedImage = finalImage.kf.decoded
                        callbackQueue.safeAsync { completionHandler?(decodedImage, nil, url, data) }
                    } else {
                        callbackQueue.safeAsync { completionHandler?(finalImage, nil, url, data) }
                    }
                    
                } else {
                    if let res = task.response as? HTTPURLResponse , res.statusCode == 304 {
                        let notModified = NSError(domain: KingfisherErrorDomain, code: KingfisherError.notModified.rawValue, userInfo: nil)
                        completionHandler?(nil, notModified, url, nil)
                        continue
                    }
                    
                    let badData = NSError(domain: KingfisherErrorDomain, code: KingfisherError.badData.rawValue, userInfo: nil)
                    callbackQueue.safeAsync { completionHandler?(nil, badData, url, nil) }
                }
            }
        }
    }

你可能感兴趣的:(KingFisher 网络请求流程)