Merge pull request #2441 from dreampiggy/performance_FLAnimatedImage_compatible_code

Revert the hack code for FLAnimatedImage compatible, because of the FLAnimatedImage initializer method block main queue.
This commit is contained in:
Bogdan Poplauschi 2018-11-12 04:44:47 +02:00 committed by GitHub
commit 0e77a30000
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 53 additions and 21 deletions

View File

@ -113,6 +113,7 @@ static inline FLAnimatedImage * SDWebImageCreateFLAnimatedImage(FLAnimatedImageV
options:(SDWebImageOptions)options
progress:(nullable SDWebImageDownloaderProgressBlock)progressBlock
completed:(nullable SDExternalCompletionBlock)completedBlock {
dispatch_group_t group = dispatch_group_create();
__weak typeof(self)weakSelf = self;
[self sd_internalSetImageWithURL:url
placeholderImage:placeholder
@ -121,6 +122,7 @@ static inline FLAnimatedImage * SDWebImageCreateFLAnimatedImage(FLAnimatedImageV
setImageBlock:^(UIImage *image, NSData *imageData) {
__strong typeof(weakSelf)strongSelf = weakSelf;
if (!strongSelf) {
dispatch_group_leave(group);
return;
}
// Step 1. Check memory cache (associate object)
@ -130,36 +132,49 @@ static inline FLAnimatedImage * SDWebImageCreateFLAnimatedImage(FLAnimatedImageV
// FLAnimatedImage framework contains a bug that cause GIF been rotated if previous rendered image orientation is not Up. We have to call `setImage:` with non-nil image to reset the state. See `https://github.com/SDWebImage/SDWebImage/issues/2402`
strongSelf.image = associatedAnimatedImage.posterImage;
strongSelf.animatedImage = associatedAnimatedImage;
dispatch_group_leave(group);
return;
}
// Step 2. Check if original compressed image data is "GIF"
BOOL isGIF = (image.sd_imageFormat == SDImageFormatGIF || [NSData sd_imageFormatForImageData:imageData] == SDImageFormatGIF);
if (!isGIF) {
// Check if placeholder, which does not trigger a backup disk cache query
BOOL isPlaceholder = (image == placeholder);
if (!isGIF || isPlaceholder) {
strongSelf.image = image;
strongSelf.animatedImage = nil;
dispatch_group_leave(group);
return;
}
// Step 3. Check if data exist or query disk cache
if (!imageData) {
NSString *key = [[SDWebImageManager sharedManager] cacheKeyForURL:url];
imageData = [[SDImageCache sharedImageCache] diskImageDataForKey:key];
}
// Step 4. Create FLAnimatedImage
FLAnimatedImage *animatedImage = SDWebImageCreateFLAnimatedImage(strongSelf, imageData);
// Step 5. Set animatedImage or normal image
if (animatedImage) {
if (strongSelf.sd_cacheFLAnimatedImage) {
image.sd_FLAnimatedImage = animatedImage;
// Hack, mark we need should use dispatch group notify for completedBlock
objc_setAssociatedObject(group, &SDWebImageInternalSetImageGroupKey, @(YES), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
// Step 3. Check if data exist or query disk cache
__block NSData *gifData = imageData;
if (!gifData) {
NSString *key = [[SDWebImageManager sharedManager] cacheKeyForURL:url];
gifData = [[SDImageCache sharedImageCache] diskImageDataForKey:key];
}
strongSelf.image = animatedImage.posterImage;
strongSelf.animatedImage = animatedImage;
} else {
strongSelf.image = image;
strongSelf.animatedImage = nil;
}
// Step 4. Create FLAnimatedImage
FLAnimatedImage *animatedImage = SDWebImageCreateFLAnimatedImage(strongSelf, gifData);
dispatch_async(dispatch_get_main_queue(), ^{
// Step 5. Set animatedImage or normal image
if (animatedImage) {
if (strongSelf.sd_cacheFLAnimatedImage) {
image.sd_FLAnimatedImage = animatedImage;
}
strongSelf.image = animatedImage.posterImage;
strongSelf.animatedImage = animatedImage;
} else {
strongSelf.image = image;
strongSelf.animatedImage = nil;
}
dispatch_group_leave(group);
});
});
}
progress:progressBlock
completed:completedBlock];
completed:completedBlock
context:@{SDWebImageInternalSetImageGroupKey : group}];
}
@end

View File

@ -13,7 +13,7 @@
/**
A Dispatch group to maintain setImageBlock and completionBlock. This key should be used only internally and may be changed in the future. (dispatch_group_t)
*/
FOUNDATION_EXPORT NSString * _Nonnull const SDWebImageInternalSetImageGroupKey __deprecated_msg("Key Deprecated. Does nothing. This key should be used only internally");
FOUNDATION_EXPORT NSString * _Nonnull const SDWebImageInternalSetImageGroupKey;
/**
A SDWebImageManager instance to control the image download and cache process using in UIImageView+WebCache category and likes. If not provided, use the shared manager (SDWebImageManager)
*/

View File

@ -64,7 +64,11 @@ static char TAG_ACTIVITY_SHOW;
[self sd_cancelImageLoadOperationWithKey:validOperationKey];
objc_setAssociatedObject(self, &imageURLKey, url, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
dispatch_group_t group = context[SDWebImageInternalSetImageGroupKey];
if (!(options & SDWebImageDelayPlaceholder)) {
if (group) {
dispatch_group_enter(group);
}
dispatch_main_async_safe(^{
[self sd_setImage:placeholder imageData:nil basedOnClassOrViaCustomSetImageBlock:setImageBlock];
});
@ -147,12 +151,25 @@ static char TAG_ACTIVITY_SHOW;
}
#endif
dispatch_main_async_safe(^{
if (group) {
dispatch_group_enter(group);
}
#if SD_UIKIT || SD_MAC
[sself sd_setImage:targetImage imageData:targetData basedOnClassOrViaCustomSetImageBlock:setImageBlock transition:transition cacheType:cacheType imageURL:imageURL];
#else
[sself sd_setImage:targetImage imageData:targetData basedOnClassOrViaCustomSetImageBlock:setImageBlock];
#endif
callCompletedBlockClojure();
if (group) {
// compatible code for FLAnimatedImage, because we assume completedBlock called after image was set. This will be removed in 5.x
BOOL shouldUseGroup = [objc_getAssociatedObject(group, &SDWebImageInternalSetImageGroupKey) boolValue];
if (shouldUseGroup) {
dispatch_group_notify(group, dispatch_get_main_queue(), callCompletedBlockClojure);
} else {
callCompletedBlockClojure();
}
} else {
callCompletedBlockClojure();
}
});
}];
[self sd_setImageLoadOperation:operation forKey:validOperationKey];