Fix missing images

Summary:
Under rare and as-yet-to-be determined circumstances, images can sometimes fail to load/download and get "stuck", without producing an error.

Because the `RCTNetworkTask` for these images is stuck in the "in progress" state, they clog up the RCTImageLoader task queue, which has a limit of 4 concurrent in-progress tasks.

This was previously masked by the fact that we automatically cancelled image requests when the RCTImageView moved offscreen, but we no longer do that.

This diff adds logic to detect some types of stuck task and remove them, thereby unblocking the queue. I've also restored the functionality of cancelling downloads for offscreen images (but not unloading the image itself) so that stuck images will be cancelled when you move to another screen, instead of using up space in the queue forever.

Reviewed By: fkgozali

Differential Revision: D3398105

fbshipit-source-id: 75ee40d06a872ae8e1cb57f02f9cad57c459143c
This commit is contained in:
Nick Lockwood
2016-06-09 09:55:18 -07:00
committed by Facebook Github Bot 3
parent a05e05fafb
commit 235749ba19
4 changed files with 35 additions and 19 deletions

View File

@@ -63,35 +63,40 @@ RCT_NOT_IMPLEMENTED(- (instancetype)init)
- (void)cancel
{
_status = RCTNetworkTaskFinished;
__strong id strongToken = _requestToken;
if (strongToken && [_handler respondsToSelector:@selector(cancelRequest:)]) {
[_handler cancelRequest:strongToken];
}
[self invalidate];
_status = RCTNetworkTaskFinished;
}
- (BOOL)validateRequestToken:(id)requestToken
{
BOOL valid = YES;
if (_requestToken == nil) {
if (requestToken == nil) {
return NO;
if (RCT_DEBUG) {
RCTLogError(@"Missing request token for request: %@", _request);
}
valid = NO;
}
_requestToken = requestToken;
}
if (![requestToken isEqual:_requestToken]) {
} else if (![requestToken isEqual:_requestToken]) {
if (RCT_DEBUG) {
RCTLogError(@"Unrecognized request token: %@ expected: %@", requestToken, _requestToken);
}
valid = NO;
}
if (!valid) {
_status = RCTNetworkTaskFinished;
if (_completionBlock) {
_completionBlock(_response, _data, [NSError errorWithDomain:RCTErrorDomain code:0
userInfo:@{NSLocalizedDescriptionKey: @"Unrecognized request token."}]);
_completionBlock(_response, nil, [NSError errorWithDomain:RCTErrorDomain code:0
userInfo:@{NSLocalizedDescriptionKey: @"Invalid request token."}]);
}
[self invalidate];
_status = RCTNetworkTaskFinished;
return NO;
}
return YES;
return valid;
}
- (void)URLRequest:(id)requestToken didSendDataWithProgress:(int64_t)bytesSent
@@ -132,11 +137,11 @@ RCT_NOT_IMPLEMENTED(- (instancetype)init)
- (void)URLRequest:(id)requestToken didCompleteWithError:(NSError *)error
{
if ([self validateRequestToken:requestToken]) {
_status = RCTNetworkTaskFinished;
if (_completionBlock) {
_completionBlock(_response, _data, error);
}
[self invalidate];
_status = RCTNetworkTaskFinished;
}
}