mirror of
https://github.com/TextureGroup/Texture.git
synced 2026-04-07 19:17:39 +00:00
Add download progress support to ASNetworkImageNode (#1489)
This commit is contained in:
@@ -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
|
||||
|
||||
|
||||
|
||||
@@ -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];
|
||||
|
||||
Reference in New Issue
Block a user