Committed by
GitHub
Merge pull request #2162 from dreampiggy/feature_query_cache_options
Feature query cache options
Showing
6 changed files
with
81 additions
and
30 deletions
@@ -46,8 +46,10 @@ | @@ -46,8 +46,10 @@ | ||
46 | options:(SDWebImageOptions)options | 46 | options:(SDWebImageOptions)options |
47 | progress:(nullable SDWebImageDownloaderProgressBlock)progressBlock | 47 | progress:(nullable SDWebImageDownloaderProgressBlock)progressBlock |
48 | completed:(nullable SDExternalCompletionBlock)completedBlock { | 48 | completed:(nullable SDExternalCompletionBlock)completedBlock { |
49 | - __weak typeof(self)weakSelf = self; | 49 | + options |= SDWebImageQueryDiskDataWhenInMemory; |
50 | + options |= SDWebImageQueryDiskDataSync; | ||
50 | dispatch_group_t group = dispatch_group_create(); | 51 | dispatch_group_t group = dispatch_group_create(); |
52 | + __weak typeof(self)weakSelf = self; | ||
51 | [self sd_internalSetImageWithURL:url | 53 | [self sd_internalSetImageWithURL:url |
52 | placeholderImage:placeholder | 54 | placeholderImage:placeholder |
53 | options:options | 55 | options:options |
@@ -25,6 +25,17 @@ typedef NS_ENUM(NSInteger, SDImageCacheType) { | @@ -25,6 +25,17 @@ typedef NS_ENUM(NSInteger, SDImageCacheType) { | ||
25 | SDImageCacheTypeMemory | 25 | SDImageCacheTypeMemory |
26 | }; | 26 | }; |
27 | 27 | ||
28 | +typedef NS_OPTIONS(NSUInteger, SDImageCacheOptions) { | ||
29 | + /** | ||
30 | + * By default, we do not query disk cache when the image is cached in memory. This mask can force query disk data at the same time. | ||
31 | + */ | ||
32 | + SDImageCacheQueryDiskDataWhenInMemory = 1 << 0, | ||
33 | + /** | ||
34 | + * By default, we query the memory cache synchonized, disk cache asynchronized. This mask can force to query disk cache synchonized. | ||
35 | + */ | ||
36 | + SDImageCacheQueryDiskDataSync = 1 << 1 | ||
37 | +}; | ||
38 | + | ||
28 | typedef void(^SDCacheQueryCompletedBlock)(UIImage * _Nullable image, NSData * _Nullable data, SDImageCacheType cacheType); | 39 | typedef void(^SDCacheQueryCompletedBlock)(UIImage * _Nullable image, NSData * _Nullable data, SDImageCacheType cacheType); |
29 | 40 | ||
30 | typedef void(^SDWebImageCheckCacheCompletionBlock)(BOOL isInCache); | 41 | typedef void(^SDWebImageCheckCacheCompletionBlock)(BOOL isInCache); |
@@ -167,6 +178,17 @@ typedef void(^SDWebImageCalculateSizeBlock)(NSUInteger fileCount, NSUInteger tot | @@ -167,6 +178,17 @@ typedef void(^SDWebImageCalculateSizeBlock)(NSUInteger fileCount, NSUInteger tot | ||
167 | - (nullable NSOperation *)queryCacheOperationForKey:(nullable NSString *)key done:(nullable SDCacheQueryCompletedBlock)doneBlock; | 178 | - (nullable NSOperation *)queryCacheOperationForKey:(nullable NSString *)key done:(nullable SDCacheQueryCompletedBlock)doneBlock; |
168 | 179 | ||
169 | /** | 180 | /** |
181 | + * Operation that queries the cache asynchronously and call the completion when done. | ||
182 | + * | ||
183 | + * @param key The unique key used to store the wanted image | ||
184 | + * @param options A mask to specify options to use for this cache query | ||
185 | + * @param doneBlock The completion block. Will not get called if the operation is cancelled | ||
186 | + * | ||
187 | + * @return a NSOperation instance containing the cache op | ||
188 | + */ | ||
189 | +- (nullable NSOperation *)queryCacheOperationForKey:(nullable NSString *)key options:(SDImageCacheOptions)options done:(nullable SDCacheQueryCompletedBlock)doneBlock; | ||
190 | + | ||
191 | +/** | ||
170 | * Query the memory cache synchronously. | 192 | * Query the memory cache synchronously. |
171 | * | 193 | * |
172 | * @param key The unique key used to store the image | 194 | * @param key The unique key used to store the image |
@@ -322,6 +322,10 @@ FOUNDATION_STATIC_INLINE NSUInteger SDCacheCostForImage(UIImage *image) { | @@ -322,6 +322,10 @@ FOUNDATION_STATIC_INLINE NSUInteger SDCacheCostForImage(UIImage *image) { | ||
322 | 322 | ||
323 | - (nullable UIImage *)diskImageForKey:(nullable NSString *)key { | 323 | - (nullable UIImage *)diskImageForKey:(nullable NSString *)key { |
324 | NSData *data = [self diskImageDataBySearchingAllPathsForKey:key]; | 324 | NSData *data = [self diskImageDataBySearchingAllPathsForKey:key]; |
325 | + return [self diskImageForKey:key data:data]; | ||
326 | +} | ||
327 | + | ||
328 | +- (nullable UIImage *)diskImageForKey:(nullable NSString *)key data:(nullable NSData *)data { | ||
325 | if (data) { | 329 | if (data) { |
326 | UIImage *image = [[SDWebImageCodersManager sharedInstance] decodedImageWithData:data]; | 330 | UIImage *image = [[SDWebImageCodersManager sharedInstance] decodedImageWithData:data]; |
327 | image = [self scaledImageForKey:key image:image]; | 331 | image = [self scaledImageForKey:key image:image]; |
@@ -338,50 +342,64 @@ FOUNDATION_STATIC_INLINE NSUInteger SDCacheCostForImage(UIImage *image) { | @@ -338,50 +342,64 @@ FOUNDATION_STATIC_INLINE NSUInteger SDCacheCostForImage(UIImage *image) { | ||
338 | return SDScaledImageForKey(key, image); | 342 | return SDScaledImageForKey(key, image); |
339 | } | 343 | } |
340 | 344 | ||
341 | -- (nullable NSOperation *)queryCacheOperationForKey:(nullable NSString *)key done:(nullable SDCacheQueryCompletedBlock)doneBlock { | 345 | +- (NSOperation *)queryCacheOperationForKey:(NSString *)key done:(SDCacheQueryCompletedBlock)doneBlock { |
346 | + return [self queryCacheOperationForKey:key options:0 done:doneBlock]; | ||
347 | +} | ||
348 | + | ||
349 | +- (nullable NSOperation *)queryCacheOperationForKey:(nullable NSString *)key options:(SDImageCacheOptions)options done:(nullable SDCacheQueryCompletedBlock)doneBlock { | ||
342 | if (!key) { | 350 | if (!key) { |
343 | if (doneBlock) { | 351 | if (doneBlock) { |
344 | doneBlock(nil, nil, SDImageCacheTypeNone); | 352 | doneBlock(nil, nil, SDImageCacheTypeNone); |
345 | } | 353 | } |
346 | return nil; | 354 | return nil; |
347 | } | 355 | } |
348 | - | 356 | + |
349 | // First check the in-memory cache... | 357 | // First check the in-memory cache... |
350 | UIImage *image = [self imageFromMemoryCacheForKey:key]; | 358 | UIImage *image = [self imageFromMemoryCacheForKey:key]; |
351 | - if (image) { | ||
352 | - NSData *diskData = nil; | ||
353 | - if (image.images) { | ||
354 | - diskData = [self diskImageDataBySearchingAllPathsForKey:key]; | ||
355 | - } | 359 | + if (image && !(options & SDImageCacheQueryDiskDataWhenInMemory)) { |
356 | if (doneBlock) { | 360 | if (doneBlock) { |
357 | - doneBlock(image, diskData, SDImageCacheTypeMemory); | 361 | + doneBlock(image, nil, SDImageCacheTypeMemory); |
358 | } | 362 | } |
359 | return nil; | 363 | return nil; |
360 | } | 364 | } |
361 | - | 365 | + |
362 | NSOperation *operation = [NSOperation new]; | 366 | NSOperation *operation = [NSOperation new]; |
363 | - dispatch_async(self.ioQueue, ^{ | 367 | + void(^queryDiskBlock)(void) = ^{ |
364 | if (operation.isCancelled) { | 368 | if (operation.isCancelled) { |
365 | // do not call the completion if cancelled | 369 | // do not call the completion if cancelled |
366 | return; | 370 | return; |
367 | } | 371 | } |
368 | - | 372 | + |
369 | @autoreleasepool { | 373 | @autoreleasepool { |
370 | NSData *diskData = [self diskImageDataBySearchingAllPathsForKey:key]; | 374 | NSData *diskData = [self diskImageDataBySearchingAllPathsForKey:key]; |
371 | - UIImage *diskImage = [self diskImageForKey:key]; | ||
372 | - if (diskImage && self.config.shouldCacheImagesInMemory) { | ||
373 | - NSUInteger cost = SDCacheCostForImage(diskImage); | ||
374 | - [self.memCache setObject:diskImage forKey:key cost:cost]; | 375 | + UIImage *diskImage = image; |
376 | + if (!diskImage && diskData) { | ||
377 | + // decode image data only if in-memory cache missed | ||
378 | + diskImage = [self diskImageForKey:key data:diskData]; | ||
379 | + if (diskImage && self.config.shouldCacheImagesInMemory) { | ||
380 | + NSUInteger cost = SDCacheCostForImage(diskImage); | ||
381 | + [self.memCache setObject:diskImage forKey:key cost:cost]; | ||
382 | + } | ||
375 | } | 383 | } |
376 | - | 384 | + |
377 | if (doneBlock) { | 385 | if (doneBlock) { |
378 | - dispatch_async(dispatch_get_main_queue(), ^{ | 386 | + if (options & SDImageCacheQueryDiskDataSync) { |
379 | doneBlock(diskImage, diskData, SDImageCacheTypeDisk); | 387 | doneBlock(diskImage, diskData, SDImageCacheTypeDisk); |
380 | - }); | 388 | + } else { |
389 | + dispatch_async(dispatch_get_main_queue(), ^{ | ||
390 | + doneBlock(diskImage, diskData, SDImageCacheTypeDisk); | ||
391 | + }); | ||
392 | + } | ||
381 | } | 393 | } |
382 | } | 394 | } |
383 | - }); | ||
384 | - | 395 | + }; |
396 | + | ||
397 | + if (options & SDImageCacheQueryDiskDataSync) { | ||
398 | + queryDiskBlock(); | ||
399 | + } else { | ||
400 | + dispatch_async(self.ioQueue, queryDiskBlock); | ||
401 | + } | ||
402 | + | ||
385 | return operation; | 403 | return operation; |
386 | } | 404 | } |
387 | 405 |
@@ -105,13 +105,6 @@ static const CGFloat kDestSeemOverlap = 2.0f; // the numbers of pixels to over | @@ -105,13 +105,6 @@ static const CGFloat kDestSeemOverlap = 2.0f; // the numbers of pixels to over | ||
105 | return nil; | 105 | return nil; |
106 | } | 106 | } |
107 | 107 | ||
108 | - SDImageFormat format = [NSData sd_imageFormatForImageData:data]; | ||
109 | - if (format == SDImageFormatGIF) { | ||
110 | - // static single GIF need to be created animated for `FLAnimatedImage` logic | ||
111 | - // GIF does not support EXIF image orientation | ||
112 | - image = [UIImage animatedImageWithImages:@[image] duration:image.duration]; | ||
113 | - return image; | ||
114 | - } | ||
115 | UIImageOrientation orientation = [[self class] sd_imageOrientationFromImageData:data]; | 108 | UIImageOrientation orientation = [[self class] sd_imageOrientationFromImageData:data]; |
116 | if (orientation != UIImageOrientationUp) { | 109 | if (orientation != UIImageOrientationUp) { |
117 | image = [UIImage imageWithCGImage:image.CGImage | 110 | image = [UIImage imageWithCGImage:image.CGImage |
@@ -94,7 +94,19 @@ typedef NS_OPTIONS(NSUInteger, SDWebImageOptions) { | @@ -94,7 +94,19 @@ typedef NS_OPTIONS(NSUInteger, SDWebImageOptions) { | ||
94 | * images to a size compatible with the constrained memory of devices. | 94 | * images to a size compatible with the constrained memory of devices. |
95 | * If `SDWebImageProgressiveDownload` flag is set the scale down is deactivated. | 95 | * If `SDWebImageProgressiveDownload` flag is set the scale down is deactivated. |
96 | */ | 96 | */ |
97 | - SDWebImageScaleDownLargeImages = 1 << 12 | 97 | + SDWebImageScaleDownLargeImages = 1 << 12, |
98 | + | ||
99 | + /** | ||
100 | + * By default, we do not query disk cache when the image is cached in memory. This mask can force query disk data at the same time. | ||
101 | + * This options is recommend to be used with `SDWebImageQueryDiskDataSync` to ensure the image is loaded in the same runloop. | ||
102 | + */ | ||
103 | + SDWebImageQueryDiskDataWhenInMemory = 1 << 13, | ||
104 | + | ||
105 | + /** | ||
106 | + * By default, we query the memory cache synchonized, disk cache asynchronized. This mask can force to query disk cache synchonized to ensure that image is loaded in the same runloop. | ||
107 | + * This can avoid flashing during cell reuse if you disable memory cache or in some other cases. | ||
108 | + */ | ||
109 | + SDWebImageQueryDiskDataSync = 1 << 14 | ||
98 | }; | 110 | }; |
99 | 111 | ||
100 | typedef void(^SDExternalCompletionBlock)(UIImage * _Nullable image, NSError * _Nullable error, SDImageCacheType cacheType, NSURL * _Nullable imageURL); | 112 | typedef void(^SDExternalCompletionBlock)(UIImage * _Nullable image, NSError * _Nullable error, SDImageCacheType cacheType, NSURL * _Nullable imageURL); |
@@ -143,8 +143,12 @@ | @@ -143,8 +143,12 @@ | ||
143 | [self.runningOperations addObject:operation]; | 143 | [self.runningOperations addObject:operation]; |
144 | } | 144 | } |
145 | NSString *key = [self cacheKeyForURL:url]; | 145 | NSString *key = [self cacheKeyForURL:url]; |
146 | + | ||
147 | + SDImageCacheOptions cacheOptions = 0; | ||
148 | + if (options & SDWebImageQueryDiskDataWhenInMemory) cacheOptions |= SDImageCacheQueryDiskDataWhenInMemory; | ||
149 | + if (options & SDWebImageQueryDiskDataSync) cacheOptions |= SDImageCacheQueryDiskDataSync; | ||
146 | 150 | ||
147 | - operation.cacheOperation = [self.imageCache queryCacheOperationForKey:key done:^(UIImage *cachedImage, NSData *cachedData, SDImageCacheType cacheType) { | 151 | + operation.cacheOperation = [self.imageCache queryCacheOperationForKey:key options:cacheOptions done:^(UIImage *cachedImage, NSData *cachedData, SDImageCacheType cacheType) { |
148 | if (operation.isCancelled) { | 152 | if (operation.isCancelled) { |
149 | [self safelyRemoveOperationFromRunning:operation]; | 153 | [self safelyRemoveOperationFromRunning:operation]; |
150 | return; | 154 | return; |
-
Please register or login to post a comment