美文网首页
32期_SDWebImage的缓存查找

32期_SDWebImage的缓存查找

作者: 萧修 | 来源:发表于2023-09-03 01:00 被阅读0次

    涉及的类SDImageCache,可从SDWebImageManager入手
    为其一个属性。所有图片加载都通过这个。

    @interface SDWebImageManager : NSObject
    
    @property (strong, nonatomic], readonly, nonnull) id<SDImageCache> imageCache;
    
    @end
    

    SDImageCache

    @interface SDImageCache : NSObject
    @property (nonatomic, copy, nonnull, readonly) SDImageCacheConfig *config;
    
    @property (nonatomic, strong, readonly, nonnull) id<SDMemoryCache> memoryCache;
    
    @property (nonatomic, strong, readonly, nonnull) id<SDDiskCache> diskCache;
    @end
    

    缓存策略

    @interface SDImageCacheConfig : NSObject <NSCopying>
    
    @property (assign, nonatomic) BOOL shouldCacheImagesInMemory;
    
    @property (assign, nonatomic) BOOL shouldUseWeakMemoryCache;
    @end
    
    

    该类有内存缓存和磁盘缓存两种

    SDMemoryCache.m
    
    - (nullable SDImageCacheToken *)queryCacheOperationForKey:(nullable NSString *)key options:(SDImageCacheOptions)options context:(nullable SDWebImageContext *)context cacheType:(SDImageCacheType)queryCacheType done:(nullable SDImageCacheQueryCompletionBlock)doneBlock {
        if (!key) {
            if (doneBlock) {
                doneBlock(nil, nil, SDImageCacheTypeNone);
            }
            return nil;
        }
        // Invalid cache type
        if (queryCacheType == SDImageCacheTypeNone) {
            if (doneBlock) {
                doneBlock(nil, nil, SDImageCacheTypeNone);
            }
            return nil;
        }
        
        // First check the in-memory cache...
        UIImage *image;
        if (queryCacheType != SDImageCacheTypeDisk) {
            image = [self imageFromMemoryCacheForKey:key];
        }
        
        是否仅仅读取内存,仅仅读取磁盘等判断
        
        之后加载磁盘
        ...
        NSData* (^queryDiskDataBlock)(void) = ^NSData* {
            @synchronized (operation) {
                if (operation.isCancelled) {
                    return nil;
                }
            }
            
            return [self diskImageDataBySearchingAllPathsForKey:key];
        };
    }
    

    imageFromMemoryCacheForKey标志要从内存读取,当查不到时,

    diskImageDataBySearchingAllPathsForKey标志从磁盘读取

    内存缓存

    • SDMemoryCache
    @interface SDMemoryCache <KeyType, ObjectType> : NSCache <KeyType, ObjectType> <SDMemoryCache>
    
    @property (nonatomic, strong, nonnull, readonly) SDImageCacheConfig *config;
    
    @end
    
    
    • imageFromMemoryCacheForKey
    SDImageCache.m
    
    - (nullable UIImage *)imageFromMemoryCacheForKey:(nullable NSString *)key {
        return [self.memoryCache objectForKey:key];
    }
    
    • objectForKey
    SDMemoryCache.m
    
    - (id)objectForKey:(id)key {
        id obj = [super objectForKey:key];
        if (!self.config.shouldUseWeakMemoryCache) {
            return obj;
        }
        if (key && !obj) {
            // Check weak cache
            SD_LOCK(_weakCacheLock);
            obj = [self.weakCache objectForKey:key];
            SD_UNLOCK(_weakCacheLock);
            if (obj) {
                // Sync cache
                NSUInteger cost = 0;
                if ([obj isKindOfClass:[UIImage class]]) {
                    cost = [(UIImage *)obj sd_memoryCost];
                }
                [super setObject:obj forKey:key cost:cost];
            }
        }
        return obj;
    }
    

    磁盘缓存

    @interface SDDiskCache : NSObject <SDDiskCache>
    
    @property (nonatomic, strong, readonly, nonnull) SDImageCacheConfig *config;
    
    - (nonnull instancetype)init NS_UNAVAILABLE;
    
    - (void)moveCacheDirectoryFromPath:(nonnull NSString *)srcPath toPath:(nonnull NSString *)dstPath;
    
    @end
    
    • diskImageDataBySearchingAllPathsForKey
    - (nullable NSData *)diskImageDataBySearchingAllPathsForKey:(nullable NSString *)key {
        if (!key) {
            return nil;
        }
        
        NSData *data = [self.diskCache dataForKey:key];
        if (data) {
            return data;
        }
        
        // Addtional cache path for custom pre-load cache
        if (self.additionalCachePathBlock) {
            NSString *filePath = self.additionalCachePathBlock(key);
            if (filePath) {
                data = [NSData dataWithContentsOfFile:filePath options:self.config.diskCacheReadingOptions error:nil];
            }
        }
    
        return data;
    }
    
    
    • dataForKey
    - (NSData *)dataForKey:(NSString *)key {
        NSParameterAssert(key);
        NSString *filePath = [self cachePathForKey:key];
        NSData *data = [NSData dataWithContentsOfFile:filePath options:self.config.diskCacheReadingOptions error:nil];
        if (data) {
            return data;
        }
        
        // fallback because of https://github.com/rs/SDWebImage/pull/976 that added the extension to the disk file name
        // checking the key with and without the extension
        data = [NSData dataWithContentsOfFile:filePath.stringByDeletingPathExtension options:self.config.diskCacheReadingOptions error:nil];
        if (data) {
            return data;
        }
        
        return nil;
    }
    
    • cachePathForKey
    - (nullable NSString *)cachePathForKey:(NSString *)key {
        NSParameterAssert(key);
        return [self cachePathForKey:key inPath:self.diskCachePath];
    }
    
    • cachePathForKey:inPath
    - (nullable NSString *)cachePathForKey:(nullable NSString *)key inPath:(nonnull NSString *)path {
        NSString *filename = SDDiskCacheFileNameForKey(key);
        return [path stringByAppendingPathComponent:filename];
    }
    
    

    SDDiskCacheFileNameForKey为磁盘中MD5转换

    磁盘缓存查找用到了gcd

    内存缓存和磁盘缓存执行完毕之后,还会进入下载涉及的类SDImageLoader

    相关文章

      网友评论

          本文标题:32期_SDWebImage的缓存查找

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