Keep the progressive decoding process only exist one per image download. Cancel the unused progressive decoding when full pixel data is available.
This commit is contained in:
parent
c975288eb4
commit
3d1280315b
|
@ -54,7 +54,7 @@ typedef NSMutableDictionary<NSString *, id> SDCallbacksDictionary;
|
||||||
|
|
||||||
@property (strong, nonatomic, readwrite, nullable) NSURLSessionTaskMetrics *metrics API_AVAILABLE(macosx(10.12), ios(10.0), watchos(3.0), tvos(10.0));
|
@property (strong, nonatomic, readwrite, nullable) NSURLSessionTaskMetrics *metrics API_AVAILABLE(macosx(10.12), ios(10.0), watchos(3.0), tvos(10.0));
|
||||||
|
|
||||||
@property (strong, nonatomic, nonnull) dispatch_queue_t coderQueue; // the queue to do image decoding
|
@property (strong, nonatomic, nonnull) NSOperationQueue *coderQueue; // the serial operation queue to do image decoding
|
||||||
#if SD_UIKIT
|
#if SD_UIKIT
|
||||||
@property (assign, nonatomic) UIBackgroundTaskIdentifier backgroundTaskId;
|
@property (assign, nonatomic) UIBackgroundTaskIdentifier backgroundTaskId;
|
||||||
#endif
|
#endif
|
||||||
|
@ -89,7 +89,8 @@ typedef NSMutableDictionary<NSString *, id> SDCallbacksDictionary;
|
||||||
_finished = NO;
|
_finished = NO;
|
||||||
_expectedSize = 0;
|
_expectedSize = 0;
|
||||||
_unownedSession = session;
|
_unownedSession = session;
|
||||||
_coderQueue = dispatch_queue_create("com.hackemist.SDWebImageDownloaderOperationCoderQueue", DISPATCH_QUEUE_SERIAL);
|
_coderQueue = [NSOperationQueue new];
|
||||||
|
_coderQueue.maxConcurrentOperationCount = 1;
|
||||||
#if SD_UIKIT
|
#if SD_UIKIT
|
||||||
_backgroundTaskId = UIBackgroundTaskInvalid;
|
_backgroundTaskId = UIBackgroundTaskInvalid;
|
||||||
#endif
|
#endif
|
||||||
|
@ -384,17 +385,18 @@ didReceiveResponse:(NSURLResponse *)response
|
||||||
// Get the image data
|
// Get the image data
|
||||||
NSData *imageData = [self.imageData copy];
|
NSData *imageData = [self.imageData copy];
|
||||||
|
|
||||||
// progressive decode the image in coder queue
|
// keep maxmium one progressive decode process during download
|
||||||
dispatch_async(self.coderQueue, ^{
|
if (self.coderQueue.operationCount == 0) {
|
||||||
@autoreleasepool {
|
// NSOperation have autoreleasepool, don't need to create extra one
|
||||||
|
[self.coderQueue addOperationWithBlock:^{
|
||||||
UIImage *image = SDImageLoaderDecodeProgressiveImageData(imageData, self.request.URL, finished, self, [[self class] imageOptionsFromDownloaderOptions:self.options], self.context);
|
UIImage *image = SDImageLoaderDecodeProgressiveImageData(imageData, self.request.URL, finished, self, [[self class] imageOptionsFromDownloaderOptions:self.options], self.context);
|
||||||
if (image) {
|
if (image) {
|
||||||
// We do not keep the progressive decoding image even when `finished`=YES. Because they are for view rendering but not take full function from downloader options. And some coders implementation may not keep consistent between progressive decoding and normal decoding.
|
// We do not keep the progressive decoding image even when `finished`=YES. Because they are for view rendering but not take full function from downloader options. And some coders implementation may not keep consistent between progressive decoding and normal decoding.
|
||||||
|
|
||||||
[self callCompletionBlocksWithImage:image imageData:nil error:nil finished:NO];
|
[self callCompletionBlocksWithImage:image imageData:nil error:nil finished:NO];
|
||||||
}
|
}
|
||||||
}
|
}];
|
||||||
});
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (SDWebImageDownloaderProgressBlock progressBlock in [self callbacksForKey:kProgressCallbackKey]) {
|
for (SDWebImageDownloaderProgressBlock progressBlock in [self callbacksForKey:kProgressCallbackKey]) {
|
||||||
|
@ -461,19 +463,18 @@ didReceiveResponse:(NSURLResponse *)response
|
||||||
[self callCompletionBlocksWithError:self.responseError];
|
[self callCompletionBlocksWithError:self.responseError];
|
||||||
[self done];
|
[self done];
|
||||||
} else {
|
} else {
|
||||||
// decode the image in coder queue
|
// decode the image in coder queue, cancel all previous decoding process
|
||||||
dispatch_async(self.coderQueue, ^{
|
[self.coderQueue cancelAllOperations];
|
||||||
@autoreleasepool {
|
[self.coderQueue addOperationWithBlock:^{
|
||||||
UIImage *image = SDImageLoaderDecodeImageData(imageData, self.request.URL, [[self class] imageOptionsFromDownloaderOptions:self.options], self.context);
|
UIImage *image = SDImageLoaderDecodeImageData(imageData, self.request.URL, [[self class] imageOptionsFromDownloaderOptions:self.options], self.context);
|
||||||
CGSize imageSize = image.size;
|
CGSize imageSize = image.size;
|
||||||
if (imageSize.width == 0 || imageSize.height == 0) {
|
if (imageSize.width == 0 || imageSize.height == 0) {
|
||||||
[self callCompletionBlocksWithError:[NSError errorWithDomain:SDWebImageErrorDomain code:SDWebImageErrorBadImageData userInfo:@{NSLocalizedDescriptionKey : @"Downloaded image has 0 pixels"}]];
|
[self callCompletionBlocksWithError:[NSError errorWithDomain:SDWebImageErrorDomain code:SDWebImageErrorBadImageData userInfo:@{NSLocalizedDescriptionKey : @"Downloaded image has 0 pixels"}]];
|
||||||
} else {
|
} else {
|
||||||
[self callCompletionBlocksWithImage:image imageData:imageData error:nil finished:YES];
|
[self callCompletionBlocksWithImage:image imageData:imageData error:nil finished:YES];
|
||||||
}
|
|
||||||
[self done];
|
|
||||||
}
|
}
|
||||||
});
|
[self done];
|
||||||
|
}];
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
[self callCompletionBlocksWithError:[NSError errorWithDomain:SDWebImageErrorDomain code:SDWebImageErrorBadImageData userInfo:@{NSLocalizedDescriptionKey : @"Image data is nil"}]];
|
[self callCompletionBlocksWithError:[NSError errorWithDomain:SDWebImageErrorDomain code:SDWebImageErrorBadImageData userInfo:@{NSLocalizedDescriptionKey : @"Image data is nil"}]];
|
||||||
|
|
Loading…
Reference in New Issue