Add download progress support to ASNetworkImageNode (#1489)

This commit is contained in:
Wu Zhong
2019-07-24 22:44:16 -07:00
committed by Huy Nguyen
parent 4ebd38c316
commit 9cedd4e3e6
2 changed files with 58 additions and 2 deletions
+7
View File
@@ -133,6 +133,13 @@ NS_ASSUME_NONNULL_BEGIN
*/
@property (readonly) CGFloat renderedImageQuality;
/**
* Download progress of the current image.
* When downloading a network image, this value would be updated to track download progress (value between 0 and 1)
* This is 1 if image load from cache or network successfully.
*/
@property (readonly) CGFloat downloadProgress;
@end
+51 -2
View File
@@ -39,6 +39,7 @@
CGFloat _currentImageQuality;
CGFloat _renderedImageQuality;
CGFloat _downloadProgress;
// Immutable and set on init only. We don't need to lock in this case.
__weak id<ASImageDownloaderProtocol> _downloader;
@@ -151,6 +152,7 @@ static std::atomic_bool _useMainThreadDelegateCallbacks(true);
// If our image is being set externally, the image quality is 100%
if (imageWasSetExternally) {
[self _setCurrentImageQuality:1.0];
[self _setDownloadProgress:1.0];
}
[self _locked__setImage:image];
@@ -202,7 +204,9 @@ static std::atomic_bool _useMainThreadDelegateCallbacks(true);
_networkImageNodeFlags.imageWasSetExternally = NO;
[self _locked_cancelImageDownloadWithResumePossibility:NO];
[self _setDownloadProgress:0.0];
_networkImageNodeFlags.imageLoaded = NO;
_URL = URL;
@@ -273,6 +277,30 @@ static std::atomic_bool _useMainThreadDelegateCallbacks(true);
});
}
- (void)setDownloadProgress:(CGFloat)downloadProgress
{
ASLockScopeSelf();
_downloadProgress = downloadProgress;
}
- (CGFloat)downloadProgress
{
return ASLockedSelf(_downloadProgress);
}
/**
* Always use these methods internally to update the current download progress
* We want to maintain the order that downloadProgress is set regardless of the calling thread,
* so we always have to dispatch to the main thread to ensure that we queue the operations in the correct order.
* (see comment in displayDidFinish)
*/
- (void)_setDownloadProgress:(CGFloat)downloadProgress
{
dispatch_async(dispatch_get_main_queue(), ^{
self.downloadProgress = downloadProgress;
});
}
- (void)setRenderedImageQuality:(CGFloat)renderedImageQuality
{
ASLockScopeSelf();
@@ -363,6 +391,7 @@ static std::atomic_bool _useMainThreadDelegateCallbacks(true);
UIImage *result = [[_cache synchronouslyFetchedCachedImageWithURL:url] asdk_image];
if (result) {
[self _setCurrentImageQuality:1.0];
[self _setDownloadProgress:1.0];
[self _locked__setImage:result];
_networkImageNodeFlags.imageLoaded = YES;
@@ -438,6 +467,17 @@ static std::atomic_bool _useMainThreadDelegateCallbacks(true);
#pragma mark - Progress
- (void)_updateDownloadedProgress:(CGFloat)progress
downloadIdentifier:(nullable id)downloadIdentifier
{
ASLockScopeSelf();
// Getting a result back for a different download identifier, download must not have been successfully canceled
if (ASObjectIsEqual(_downloadIdentifier, downloadIdentifier) == NO && downloadIdentifier != nil) {
return;
}
[self _setDownloadProgress:progress];
}
- (void)handleProgressImage:(UIImage *)progressImage progress:(CGFloat)progress downloadIdentifier:(nullable id)downloadIdentifier
{
ASLockScopeSelf();
@@ -536,6 +576,7 @@ static std::atomic_bool _useMainThreadDelegateCallbacks(true);
[self _locked_setAnimatedImage:nil];
[self _setCurrentImageQuality:0.0];
[self _setDownloadProgress:0.0];
[self _locked__setImage:_defaultImage];
_networkImageNodeFlags.imageLoaded = NO;
@@ -593,7 +634,13 @@ static std::atomic_bool _useMainThreadDelegateCallbacks(true);
}
dispatch_queue_t callbackQueue = [self callbackQueue];
ASImageDownloaderProgress downloadProgress = NULL;
__weak __typeof__(self) weakSelf = self;
ASImageDownloaderProgress downloadProgress = ^(CGFloat progress){
__typeof__(self) strongSelf = weakSelf;
if (strongSelf) {
[strongSelf _updateDownloadedProgress:progress downloadIdentifier:downloadIdentifier];
}
};
ASImageDownloaderCompletion completion = ^(id <ASImageContainerProtocol> _Nullable imageContainer, NSError * _Nullable error, id _Nullable downloadIdentifier, id _Nullable userInfo) {
if (finished != NULL) {
finished(imageContainer, error, downloadIdentifier, userInfo);
@@ -727,6 +774,7 @@ static std::atomic_bool _useMainThreadDelegateCallbacks(true);
self->_networkImageNodeFlags.imageLoaded = YES;
[self _setCurrentImageQuality:1.0];
[self _setDownloadProgress:1.0];
if (self->_networkImageNodeFlags.delegateDidLoadImageWithInfo) {
ASUnlockScope(self);
@@ -766,6 +814,7 @@ static std::atomic_bool _useMainThreadDelegateCallbacks(true);
UIImage *newImage;
if (imageContainer != nil) {
[strongSelf _setCurrentImageQuality:1.0];
[strongSelf _setDownloadProgress:1.0];
NSData *animatedImageData = [imageContainer asdk_animatedImageData];
if (animatedImageData && strongSelf->_networkImageNodeFlags.downloaderImplementsAnimatedImage) {
id animatedImage = [strongSelf->_downloader animatedImageWithData:animatedImageData];