Merge pull request #3327 from soondl/fix/imageView_blink_diskDataSync

Fix imageView blinks with option 'SDImageCacheQueryDiskDataSync'
This commit is contained in:
DreamPiggy 2022-03-03 18:27:06 +08:00 committed by GitHub
commit 020481d5c8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 67 additions and 34 deletions

View File

@ -552,51 +552,60 @@ static NSString * _defaultDiskCacheDirectory;
// 2. in-memory cache miss & diskDataSync // 2. in-memory cache miss & diskDataSync
BOOL shouldQueryDiskSync = ((image && options & SDImageCacheQueryMemoryDataSync) || BOOL shouldQueryDiskSync = ((image && options & SDImageCacheQueryMemoryDataSync) ||
(!image && options & SDImageCacheQueryDiskDataSync)); (!image && options & SDImageCacheQueryDiskDataSync));
void(^queryDiskBlock)(void) = ^{ NSData* (^queryDiskDataBlock)(void) = ^NSData* {
if (operation.isCancelled) { if (operation.isCancelled) {
if (doneBlock) { return nil;
doneBlock(nil, nil, SDImageCacheTypeNone);
}
return;
} }
@autoreleasepool { return [self diskImageDataBySearchingAllPathsForKey:key];
NSData *diskData = [self diskImageDataBySearchingAllPathsForKey:key]; };
UIImage *diskImage;
if (image) { UIImage* (^queryDiskImageBlock)(NSData*) = ^UIImage*(NSData* diskData) {
// the image is from in-memory cache, but need image data if (operation.isCancelled) {
diskImage = image; return nil;
} else if (diskData) { }
BOOL shouldCacheToMomery = YES;
if (context[SDWebImageContextStoreCacheType]) { UIImage *diskImage;
SDImageCacheType cacheType = [context[SDWebImageContextStoreCacheType] integerValue]; if (image) {
shouldCacheToMomery = (cacheType == SDImageCacheTypeAll || cacheType == SDImageCacheTypeMemory); // the image is from in-memory cache, but need image data
} diskImage = image;
// decode image data only if in-memory cache missed } else if (diskData) {
diskImage = [self diskImageForKey:key data:diskData options:options context:context]; BOOL shouldCacheToMomery = YES;
if (shouldCacheToMomery && diskImage && self.config.shouldCacheImagesInMemory) { if (context[SDWebImageContextStoreCacheType]) {
NSUInteger cost = diskImage.sd_memoryCost; SDImageCacheType cacheType = [context[SDWebImageContextStoreCacheType] integerValue];
[self.memoryCache setObject:diskImage forKey:key cost:cost]; shouldCacheToMomery = (cacheType == SDImageCacheTypeAll || cacheType == SDImageCacheTypeMemory);
}
} }
// decode image data only if in-memory cache missed
if (doneBlock) { diskImage = [self diskImageForKey:key data:diskData options:options context:context];
if (shouldQueryDiskSync) { if (shouldCacheToMomery && diskImage && self.config.shouldCacheImagesInMemory) {
doneBlock(diskImage, diskData, SDImageCacheTypeDisk); NSUInteger cost = diskImage.sd_memoryCost;
} else { [self.memoryCache setObject:diskImage forKey:key cost:cost];
dispatch_async(dispatch_get_main_queue(), ^{
doneBlock(diskImage, diskData, SDImageCacheTypeDisk);
});
}
} }
} }
return diskImage;
}; };
// Query in ioQueue to keep IO-safe // Query in ioQueue to keep IO-safe
if (shouldQueryDiskSync) { if (shouldQueryDiskSync) {
dispatch_sync(self.ioQueue, queryDiskBlock); __block NSData* diskData;
__block UIImage* diskImage;
dispatch_sync(self.ioQueue, ^{
diskData = queryDiskDataBlock();
diskImage = queryDiskImageBlock(diskData);
});
if (doneBlock) {
doneBlock(diskImage, diskData, SDImageCacheTypeDisk);
}
} else { } else {
dispatch_async(self.ioQueue, queryDiskBlock); dispatch_async(self.ioQueue, ^{
NSData* diskData = queryDiskDataBlock();
UIImage* diskImage = queryDiskImageBlock(diskData);
if (doneBlock) {
dispatch_async(dispatch_get_main_queue(), ^{
doneBlock(diskImage, diskData, SDImageCacheTypeDisk);
});
}
});
} }
return operation; return operation;

View File

@ -35,6 +35,30 @@
[self waitForExpectationsWithCommonTimeout]; [self waitForExpectationsWithCommonTimeout];
} }
- (void)testUIImageViewSetImageWithURLDiskSync {
NSData *imageData = [NSData dataWithContentsOfFile:[self testJPEGPath]];
// Ensure the image is cached in disk but not memory
[SDImageCache.sharedImageCache removeImageFromMemoryForKey:kTestJPEGURL];
[SDImageCache.sharedImageCache removeImageFromDiskForKey:kTestJPEGURL];
[SDImageCache.sharedImageCache storeImageDataToDisk:imageData forKey:kTestJPEGURL];
UIImageView *imageView = [[UIImageView alloc] init];
NSURL *originalImageURL = [NSURL URLWithString:kTestJPEGURL];
[imageView sd_setImageWithURL:originalImageURL
placeholderImage:nil
options:SDWebImageQueryDiskDataSync
completed:^(UIImage * _Nullable image, NSError * _Nullable error, SDImageCacheType cacheType, NSURL * _Nullable imageURL) {
expect(image).toNot.beNil();
expect(error).to.beNil();
expect(originalImageURL).to.equal(imageURL);
expect(imageView.image).to.equal(image);
}];
expect(imageView.sd_imageURL).equal(originalImageURL);
expect(imageView.image).toNot.beNil();
}
#if SD_UIKIT #if SD_UIKIT
- (void)testUIImageViewSetHighlightedImageWithURL { - (void)testUIImageViewSetHighlightedImageWithURL {
XCTestExpectation *expectation = [self expectationWithDescription:@"UIImageView setHighlightedImageWithURL"]; XCTestExpectation *expectation = [self expectationWithDescription:@"UIImageView setHighlightedImageWithURL"];