fix(ios): cancel previous custom image loading when a new request come

This commit is contained in:
mengyanluo
2020-10-26 14:33:25 +08:00
committed by ilikethese
parent 1b776cf470
commit 3aef2466d5
+70 -45
View File
@@ -131,6 +131,7 @@ UIImage *HippyBlurredImageWithRadiusv(UIImage *inputImage, CGFloat radius)
@interface HippyImageView () {
NSURLSessionDataTask *_task;
NSURL *_imageLoadURL;
long long _totalLength;
NSMutableData *_data;
__weak CALayer *_borderWidthLayer;
@@ -267,10 +268,10 @@ UIImage *HippyBlurredImageWithRadiusv(UIImage *inputImage, CGFloat radius)
- (void)reloadImage
{
NSDictionary *source = [self.source firstObject];
if (source && CGRectGetWidth(self.frame) > 0 && CGRectGetHeight(self.frame) > 0) {
if (_onLoadStart) {
_onLoadStart(@{});
}
if (source && CGRectGetWidth(self.frame) > 0 && CGRectGetHeight(self.frame) > 0) {
if (_onLoadStart) {
_onLoadStart(@{});
}
NSString *uri = source[@"uri"];
BOOL isBlurredImage = NO;
@@ -291,7 +292,7 @@ UIImage *HippyBlurredImageWithRadiusv(UIImage *inputImage, CGFloat radius)
BOOL fileExist = [[NSFileManager defaultManager] fileExistsAtPath:localPath isDirectory:&isDirectory];
if (fileExist && !isDirectory) {
NSData *imageData = [NSData dataWithContentsOfFile:localPath];
Class<HippyImageProviderProtocol> ipClass = imageProviderClassFromBridge(imageData, _bridge);
Class<HippyImageProviderProtocol> ipClass = imageProviderClassFromBridge(imageData, self.bridge);
id<HippyImageProviderProtocol> instance = [self instanceImageProviderFromClass:ipClass imageData:imageData];
BOOL isAnimatedImage = [ipClass isAnimatedImage:imageData];
if (isAnimatedImage) {
@@ -312,19 +313,45 @@ UIImage *HippyBlurredImageWithRadiusv(UIImage *inputImage, CGFloat radius)
}
return;
}
if(_bridge.imageLoader && source_url) {
if (_defaultImage) {
self.image = _defaultImage;
__weak typeof(self) weakSelf = self;
typedef void (^HandleBase64CompletedBlock)(NSString *);
HandleBase64CompletedBlock handleBase64CompletedBlock = ^void(NSString *base64Data) {
NSRange range = [base64Data rangeOfString:@";base64,"];
if (NSNotFound != range.location) {
base64Data = [base64Data substringFromIndex:range.location + range.length];
NSData *imageData = [[NSData alloc] initWithBase64EncodedString:base64Data
options: NSDataBase64DecodingIgnoreUnknownCharacters];
Class<HippyImageProviderProtocol> ipClass = imageProviderClassFromBridge(imageData, self.bridge);
id<HippyImageProviderProtocol> instance = [self instanceImageProviderFromClass:ipClass imageData:imageData];
BOOL isAnimatedImage = [ipClass isAnimatedImage:imageData];
if (isAnimatedImage) {
if (weakSelf.animatedImageOperation) {
[weakSelf.animatedImageOperation cancel];
}
weakSelf.animatedImageOperation = [[HippyAnimatedImageOperation alloc] initWithAnimatedImageProvider:instance imageView:self imageURL:source[@"uri"]];
[animated_image_queue() addOperation:weakSelf.animatedImageOperation];
}
else {
UIImage *image = [instance image];
NSError *error = nil;
if (!image) {
error = [NSError errorWithDomain: NSURLErrorDomain code: -1 userInfo: @{NSLocalizedDescriptionKey: @"base64 url is invalidated"}];
}
[weakSelf loadImage: image url: source[@"uri"] error: error needBlur:YES needCache:YES];
}
}
__weak __typeof(self) weakSelf = self;
[_bridge.imageLoader imageView:weakSelf loadAtUrl:source_url placeholderImage:_defaultImage context: NULL progress:^(long long currentLength, long long totalLength) {
__typeof(weakSelf) strongSelf = weakSelf;
if (strongSelf.onProgress) {
strongSelf.onProgress(@{@"loaded": @((double)currentLength), @"total": @((double)totalLength)});
}
} completed:^(NSData *data, NSURL *url, NSError *error) {
__typeof(weakSelf) strongSelf = weakSelf;
Class<HippyImageProviderProtocol> ipClass = imageProviderClassFromBridge(data, strongSelf.bridge);
};
typedef void(^HandleImageCompletedBlock)(NSURL *);
HandleImageCompletedBlock handleImageCompletedBlock = ^void(NSURL *source_url) {
[weakSelf.bridge.imageLoader imageView:weakSelf loadAtUrl:source_url placeholderImage:weakSelf.defaultImage context: NULL progress:^(long long currentLength, long long totalLength) {
if (weakSelf.onProgress) {
weakSelf.onProgress(@{@"loaded": @((double)currentLength), @"total": @((double)totalLength)});
}
} completed:^(NSData *data, NSURL *url, NSError *error) {
Class<HippyImageProviderProtocol> ipClass = imageProviderClassFromBridge(data, self.bridge);
id<HippyImageProviderProtocol> instance = [self instanceImageProviderFromClass:ipClass imageData:data];
BOOL isAnimatedImage = [ipClass isAnimatedImage:data];
if (isAnimatedImage) {
@@ -334,38 +361,36 @@ UIImage *HippyBlurredImageWithRadiusv(UIImage *inputImage, CGFloat radius)
weakSelf.animatedImageOperation = [[HippyAnimatedImageOperation alloc] initWithAnimatedImageProvider:instance imageView:self imageURL:source[@"uri"]];
[animated_image_queue() addOperation:weakSelf.animatedImageOperation];
}
else {
UIImage *image = [instance image];
[weakSelf loadImage: image url: url.absoluteString error: error needBlur:YES needCache:YES];
}
}];
} else {
if ([uri hasPrefix: @"data:image/"]) {
NSString *base64Data = uri;
NSRange range = [uri rangeOfString:@";base64,"];
if (NSNotFound != range.location) {
base64Data = [uri substringFromIndex:range.location + range.length];
}
NSData *imageData = [[NSData alloc] initWithBase64EncodedString:base64Data options: NSDataBase64DecodingIgnoreUnknownCharacters];
Class<HippyImageProviderProtocol> ipClass = imageProviderClassFromBridge(imageData, self.bridge);
id<HippyImageProviderProtocol> instance = [self instanceImageProviderFromClass:ipClass imageData:imageData];
BOOL isAnimatedImage = [ipClass isAnimatedImage:imageData];
if (isAnimatedImage) {
if (_animatedImageOperation) {
[_animatedImageOperation cancel];
}
_animatedImageOperation = [[HippyAnimatedImageOperation alloc] initWithAnimatedImageProvider:instance imageView:self imageURL:source[@"uri"]];
[animated_image_queue() addOperation:_animatedImageOperation];
}
else {
UIImage *image = [instance image];
NSError *error = nil;
if (!image) {
error = [NSError errorWithDomain: NSURLErrorDomain code: -1 userInfo: @{NSLocalizedDescriptionKey: @"base64 url is invalidated"}];
}
[self loadImage: image url: source[@"uri"] error: error needBlur:YES needCache:YES];
[weakSelf loadImage: image url: source[@"uri"] error: error needBlur:YES needCache:YES];
}
}
}];
};
if(_bridge.imageLoader && source_url) {
if (_defaultImage) {
weakSelf.image = _defaultImage;
}
if ([[source_url absoluteString] hasPrefix: @"data:image/"]) {
handleBase64CompletedBlock([source_url absoluteString]);
} else {
if (_imageLoadURL) {
[_bridge.imageLoader cancelImageDownload:self withUrl:_imageLoadURL];
}
_imageLoadURL = source_url;
handleImageCompletedBlock(source_url);
}
} else {
if ([uri hasPrefix: @"data:image/"]) {
handleBase64CompletedBlock(uri);
}
else {
if (_task) {
[self cancelImageLoad];
@@ -375,8 +400,8 @@ UIImage *HippyBlurredImageWithRadiusv(UIImage *inputImage, CGFloat radius)
_task = [session dataTaskWithURL:source_url];
[_task resume];
}
}
}
}
}
}
- (void)cancelImageLoad
@@ -558,7 +583,7 @@ UIImage *HippyBlurredImageWithRadiusv(UIImage *inputImage, CGFloat radius)
// self.layer.magnificationFilter = kCAFilterTrilinear;
if (image.images) {
HippyAssert(NO, @"GIF图片不应该进入这个逻辑");
HippyAssert(NO, @"GIF should not invoke this");
}
else {
self.image = image;