Merge pull request #2483 from dreampiggy/fix_progressive_coder_queue
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:
commit
ab2be2373f
|
@ -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, 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
|
||||
@property (assign, nonatomic) UIBackgroundTaskIdentifier backgroundTaskId;
|
||||
#endif
|
||||
|
@ -89,7 +89,8 @@ typedef NSMutableDictionary<NSString *, id> SDCallbacksDictionary;
|
|||
_finished = NO;
|
||||
_expectedSize = 0;
|
||||
_unownedSession = session;
|
||||
_coderQueue = dispatch_queue_create("com.hackemist.SDWebImageDownloaderOperationCoderQueue", DISPATCH_QUEUE_SERIAL);
|
||||
_coderQueue = [NSOperationQueue new];
|
||||
_coderQueue.maxConcurrentOperationCount = 1;
|
||||
#if SD_UIKIT
|
||||
_backgroundTaskId = UIBackgroundTaskInvalid;
|
||||
#endif
|
||||
|
@ -207,8 +208,13 @@ typedef NSMutableDictionary<NSString *, id> SDCallbacksDictionary;
|
|||
if (self.dataTask) {
|
||||
if (self.options & SDWebImageDownloaderHighPriority) {
|
||||
self.dataTask.priority = NSURLSessionTaskPriorityHigh;
|
||||
self.coderQueue.qualityOfService = NSQualityOfServiceUserInteractive;
|
||||
} else if (self.options & SDWebImageDownloaderLowPriority) {
|
||||
self.dataTask.priority = NSURLSessionTaskPriorityLow;
|
||||
self.coderQueue.qualityOfService = NSQualityOfServiceBackground;
|
||||
} else {
|
||||
self.dataTask.priority = NSURLSessionTaskPriorityDefault;
|
||||
self.coderQueue.qualityOfService = NSQualityOfServiceDefault;
|
||||
}
|
||||
[self.dataTask resume];
|
||||
for (SDWebImageDownloaderProgressBlock progressBlock in [self callbacksForKey:kProgressCallbackKey]) {
|
||||
|
@ -384,17 +390,18 @@ didReceiveResponse:(NSURLResponse *)response
|
|||
// Get the image data
|
||||
NSData *imageData = [self.imageData copy];
|
||||
|
||||
// progressive decode the image in coder queue
|
||||
dispatch_async(self.coderQueue, ^{
|
||||
@autoreleasepool {
|
||||
// keep maxmium one progressive decode process during download
|
||||
if (self.coderQueue.operationCount == 0) {
|
||||
// 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);
|
||||
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.
|
||||
|
||||
[self callCompletionBlocksWithImage:image imageData:nil error:nil finished:NO];
|
||||
}
|
||||
}
|
||||
});
|
||||
}];
|
||||
}
|
||||
}
|
||||
|
||||
for (SDWebImageDownloaderProgressBlock progressBlock in [self callbacksForKey:kProgressCallbackKey]) {
|
||||
|
@ -461,19 +468,18 @@ didReceiveResponse:(NSURLResponse *)response
|
|||
[self callCompletionBlocksWithError:self.responseError];
|
||||
[self done];
|
||||
} else {
|
||||
// decode the image in coder queue
|
||||
dispatch_async(self.coderQueue, ^{
|
||||
@autoreleasepool {
|
||||
UIImage *image = SDImageLoaderDecodeImageData(imageData, self.request.URL, [[self class] imageOptionsFromDownloaderOptions:self.options], self.context);
|
||||
CGSize imageSize = image.size;
|
||||
if (imageSize.width == 0 || imageSize.height == 0) {
|
||||
[self callCompletionBlocksWithError:[NSError errorWithDomain:SDWebImageErrorDomain code:SDWebImageErrorBadImageData userInfo:@{NSLocalizedDescriptionKey : @"Downloaded image has 0 pixels"}]];
|
||||
} else {
|
||||
[self callCompletionBlocksWithImage:image imageData:imageData error:nil finished:YES];
|
||||
}
|
||||
[self done];
|
||||
// decode the image in coder queue, cancel all previous decoding process
|
||||
[self.coderQueue cancelAllOperations];
|
||||
[self.coderQueue addOperationWithBlock:^{
|
||||
UIImage *image = SDImageLoaderDecodeImageData(imageData, self.request.URL, [[self class] imageOptionsFromDownloaderOptions:self.options], self.context);
|
||||
CGSize imageSize = image.size;
|
||||
if (imageSize.width == 0 || imageSize.height == 0) {
|
||||
[self callCompletionBlocksWithError:[NSError errorWithDomain:SDWebImageErrorDomain code:SDWebImageErrorBadImageData userInfo:@{NSLocalizedDescriptionKey : @"Downloaded image has 0 pixels"}]];
|
||||
} else {
|
||||
[self callCompletionBlocksWithImage:image imageData:imageData error:nil finished:YES];
|
||||
}
|
||||
});
|
||||
[self done];
|
||||
}];
|
||||
}
|
||||
} else {
|
||||
[self callCompletionBlocksWithError:[NSError errorWithDomain:SDWebImageErrorDomain code:SDWebImageErrorBadImageData userInfo:@{NSLocalizedDescriptionKey : @"Image data is nil"}]];
|
||||
|
|
Loading…
Reference in New Issue