美文网首页
SDWebImage处理流程

SDWebImage处理流程

作者: switer_iOS | 来源:发表于2021-05-20 11:43 被阅读0次

    首先附上git地址:https://github.com/SDWebImage/SDWebImage

    附上SDWebImage类图:

    image

    附上SDWebImage步骤图:

    image

    核心模块三部分:

    1.主要调度类:SDWebImageManager;全部操作都是围绕它为中心;
    2.主要缓存类:SDImageCache;
    3.主要下载类:SDWebImageDownload;

    次要:

    4.和UIView相关的类,是对UIKit的扩展,只是方便我们调起Manager里面的功能类;
    5.SDImageCacheConfig用于配置缓存;

    问题一,SD的大概流程:

    1.通过UIImageView+WebCache作为入口,有placeholderImage的情况下,先显示占位图;
    2.通过系统类NSMapTable判断当前是否有任务在执行;
    ⭐️3.重要步骤,如图:

    image

    问题二,内存缓存模块的实现步骤:

    1.SDWebImage实现了磁盘,内存双缓存;
    2.内存缓存如何实现的:通过SDMemoryCache类来管理;
    3.通过shouldUseWeakMemoryCache的Bool值,来判断是否开启内存缓存;
    4.内存缓存有可能存在两份,NSCache和SDMemoryCache,因为NSCache不可控;

    问题三,磁盘模块的实现步骤:

    1.创建一个目录;
    2.为每一个缓存文件生成一个MD5文件名;
    3.首先检查内存缓存,再检查磁盘缓存,核心代码:

    - (nullable NSOperation *)queryCacheOperationForKey:(nullable NSString *)key options:(SDImageCacheOptions)options context:(nullable SDWebImageContext *)context done:(nullable SDImageCacheQueryCompletionBlock)doneBlock {
        if (!key) {
            if (doneBlock) {
                doneBlock(nil, nil, SDImageCacheTypeNone);
            }
            return nil;
        }
    
        id<SDImageTransformer> transformer = context[SDWebImageContextImageTransformer];
        if (transformer) {
            // grab the transformed disk image if transformer provided
            NSString *transformerKey = [transformer transformerKey];
            key = SDTransformedKeyForKey(key, transformerKey);
        }
    
        // First check the in-memory cache...
        //首先检查内存缓存…
        UIImage *image = [self imageFromMemoryCacheForKey:key];
    
        if ((options & SDImageCacheDecodeFirstFrameOnly) && image.sd_isAnimated) {
    #if SD_MAC
            image = [[NSImage alloc] initWithCGImage:image.CGImage scale:image.scale orientation:kCGImagePropertyOrientationUp];
    #else
            image = [[UIImage alloc] initWithCGImage:image.CGImage scale:image.scale orientation:image.imageOrientation];
    #endif
        }
    
        BOOL shouldQueryMemoryOnly = (image && !(options & SDImageCacheQueryMemoryData));
        if (shouldQueryMemoryOnly) {
            if (doneBlock) {
                doneBlock(image, nil, SDImageCacheTypeMemory);
            }
            return nil;
        }
    
        // Second check the disk cache...
        //第二,检查磁盘缓存…
        NSOperation *operation = [NSOperation new];
        // Check whether we need to synchronously query disk
        // 1\. in-memory cache hit & memoryDataSync
        // 2\. in-memory cache miss & diskDataSync
        BOOL shouldQueryDiskSync = ((image && options & SDImageCacheQueryMemoryDataSync) ||
                                    (!image && options & SDImageCacheQueryDiskDataSync));
        void(^queryDiskBlock)(void) =  ^{
            if (operation.isCancelled) {
                // do not call the completion if cancelled
                return;
            }
    
            @autoreleasepool {
                NSData *diskData = [self diskImageDataBySearchingAllPathsForKey:key];
                UIImage *diskImage;
                SDImageCacheType cacheType = SDImageCacheTypeNone;
                if (image) {
                    // the image is from in-memory cache, but need image data
                    diskImage = image;
                    cacheType = SDImageCacheTypeMemory;
                } else if (diskData) {
                    cacheType = SDImageCacheTypeDisk;
                    // decode image data only if in-memory cache missed
                    diskImage = [self diskImageForKey:key data:diskData options:options context:context];
                    if (diskImage && self.config.shouldCacheImagesInMemory) {
                        NSUInteger cost = diskImage.sd_memoryCost;
                        [self.memCache setObject:diskImage forKey:key cost:cost];
                    }
                }
    
                if (doneBlock) {
                    if (shouldQueryDiskSync) {
                        doneBlock(diskImage, diskData, cacheType);
                    } else {
                        dispatch_async(dispatch_get_main_queue(), ^{
                            doneBlock(diskImage, diskData, cacheType);
                        });
                    }
                }
            }
        };
    
        // Query in ioQueue to keep IO-safe
        if (shouldQueryDiskSync) {
            dispatch_sync(self.ioQueue, queryDiskBlock);
        } else {
            dispatch_async(self.ioQueue, queryDiskBlock);
        }
    
        return operation;
    }
    
    

    问题四,下载模块的实现步骤:

    1.SDWebImageDownloader实现了下载管理;围绕NSURLSession实现的;
    2.SDWebImageDownloaderOperation实现了生命周期管理,具体任务是它来实现的;
    3.核心方法SDWebImageDownloader里的:

    - (nullable NSOperation<SDWebImageDownloaderOperation> *)createDownloaderOperationWithUrl:(nonnull NSURL *)url
                                                                                      options:(SDWebImageDownloaderOptions)options
                                                                                      context:(nullable SDWebImageContext *)context {
    ...
    }
    
    

    4.SDWebImageDownloaderConfig里,SDWebImageDownloaderExecutionOrder枚举,两种情况:

    /// Operation execution order
    typedef NS_ENUM(NSInteger, SDWebImageDownloaderExecutionOrder) {
        /**
         * Default value. All download operations will execute in queue style (first-in-first-out).
         */
        SDWebImageDownloaderFIFOExecutionOrder,
    
        /**
         * All download operations will execute in stack style (last-in-first-out).
         */
        SDWebImageDownloaderLIFOExecutionOrder
    };
    
    

    FIFOE为先进先出,LIFOE为后进先出;

    相关文章

      网友评论

          本文标题:SDWebImage处理流程

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