Skip to content

Commit

Permalink
Add download progress support to ASNetworkImageNode (#1489)
Browse files Browse the repository at this point in the history
  • Loading branch information
zhongwuzw authored and nguyenhuy committed Jul 25, 2019
1 parent 4ebd38c commit 9cedd4e
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 2 deletions.
7 changes: 7 additions & 0 deletions Source/ASNetworkImageNode.h
Original file line number Diff line number Diff line change
Expand Up @@ -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


Expand Down
53 changes: 51 additions & 2 deletions Source/ASNetworkImageNode.mm
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ @interface ASNetworkImageNode ()

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;
Expand Down Expand Up @@ -151,6 +152,7 @@ - (void)_locked_setImage:(UIImage *)image
// 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];
Expand Down Expand Up @@ -202,7 +204,9 @@ - (void)setURL:(NSURL *)URL resetToDefault:(BOOL)reset
_networkImageNodeFlags.imageWasSetExternally = NO;

[self _locked_cancelImageDownloadWithResumePossibility:NO];


[self _setDownloadProgress:0.0];

_networkImageNodeFlags.imageLoaded = NO;

_URL = URL;
Expand Down Expand Up @@ -273,6 +277,30 @@ - (void)_setCurrentImageQuality:(CGFloat)imageQuality
});
}

- (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();
Expand Down Expand Up @@ -363,6 +391,7 @@ - (void)displayWillStartAsynchronously:(BOOL)asynchronously
UIImage *result = [[_cache synchronouslyFetchedCachedImageWithURL:url] asdk_image];
if (result) {
[self _setCurrentImageQuality:1.0];
[self _setDownloadProgress:1.0];
[self _locked__setImage:result];
_networkImageNodeFlags.imageLoaded = YES;

Expand Down Expand Up @@ -438,6 +467,17 @@ + (BOOL)useMainThreadDelegateCallbacks

#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();
Expand Down Expand Up @@ -536,6 +576,7 @@ - (void)_locked_cancelDownloadAndClearImageWithResumePossibility:(BOOL)storeResu

[self _locked_setAnimatedImage:nil];
[self _setCurrentImageQuality:0.0];
[self _setDownloadProgress:0.0];
[self _locked__setImage:_defaultImage];

_networkImageNodeFlags.imageLoaded = NO;
Expand Down Expand Up @@ -593,7 +634,13 @@ - (void)_downloadImageWithCompletion:(void (^)(id <ASImageContainerProtocol> ima
}

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);
Expand Down Expand Up @@ -727,6 +774,7 @@ - (void)_lazilyLoadImageIfNecessary
self->_networkImageNodeFlags.imageLoaded = YES;

[self _setCurrentImageQuality:1.0];
[self _setDownloadProgress:1.0];

if (self->_networkImageNodeFlags.delegateDidLoadImageWithInfo) {
ASUnlockScope(self);
Expand Down Expand Up @@ -766,6 +814,7 @@ - (void)_lazilyLoadImageIfNecessary
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];
Expand Down

0 comments on commit 9cedd4e

Please sign in to comment.