sdwebimage下载时获取ip在子线程进行,避免下载图片卡顿问题 review by christ
Showing
1 changed file
with
91 additions
and
107 deletions
@@ -15,7 +15,7 @@ | @@ -15,7 +15,7 @@ | ||
15 | static NSString *const kProgressCallbackKey = @"progress"; | 15 | static NSString *const kProgressCallbackKey = @"progress"; |
16 | static NSString *const kCompletedCallbackKey = @"completed"; | 16 | static NSString *const kCompletedCallbackKey = @"completed"; |
17 | 17 | ||
18 | -@interface SDWebImageDownloader ()<HttpDNSDegradationDelegate> | 18 | +@interface SDWebImageDownloader () |
19 | 19 | ||
20 | @property (strong, nonatomic) NSOperationQueue *downloadQueue; | 20 | @property (strong, nonatomic) NSOperationQueue *downloadQueue; |
21 | @property (weak, nonatomic) NSOperation *lastAddedOperation; | 21 | @property (weak, nonatomic) NSOperation *lastAddedOperation; |
@@ -25,26 +25,12 @@ static NSString *const kCompletedCallbackKey = @"completed"; | @@ -25,26 +25,12 @@ static NSString *const kCompletedCallbackKey = @"completed"; | ||
25 | // This queue is used to serialize the handling of the network responses of all the download operation in a single queue | 25 | // This queue is used to serialize the handling of the network responses of all the download operation in a single queue |
26 | @property (SDDispatchQueueSetterSementics, nonatomic) dispatch_queue_t barrierQueue; | 26 | @property (SDDispatchQueueSetterSementics, nonatomic) dispatch_queue_t barrierQueue; |
27 | 27 | ||
28 | -@property (copy, nonatomic) NSString *dnsFlag; | 28 | +@property (assign, nonatomic) BOOL enableHttpDNS; |
29 | 29 | ||
30 | @end | 30 | @end |
31 | 31 | ||
32 | @implementation SDWebImageDownloader | 32 | @implementation SDWebImageDownloader |
33 | 33 | ||
34 | -- (BOOL)shouldDegradeHTTPDNS:(NSString *)hostName | ||
35 | -{ | ||
36 | -#ifdef M0 | ||
37 | - return YES; | ||
38 | -#else | ||
39 | - | ||
40 | - if ([self.dnsFlag isEqualToString:@"2a90dfa0f37b92aaebf369e9a4d38ba4"]) { | ||
41 | - return NO; | ||
42 | - } | ||
43 | - | ||
44 | - return YES; | ||
45 | -#endif | ||
46 | -} | ||
47 | - | ||
48 | + (void)initialize { | 34 | + (void)initialize { |
49 | // Bind SDNetworkActivityIndicator if available (download it here: http://github.com/rs/SDNetworkActivityIndicator ) | 35 | // Bind SDNetworkActivityIndicator if available (download it here: http://github.com/rs/SDNetworkActivityIndicator ) |
50 | // To use it, just add #import "SDNetworkActivityIndicator.h" in addition to the SDWebImage import | 36 | // To use it, just add #import "SDNetworkActivityIndicator.h" in addition to the SDWebImage import |
@@ -93,13 +79,10 @@ static NSString *const kCompletedCallbackKey = @"completed"; | @@ -93,13 +79,10 @@ static NSString *const kCompletedCallbackKey = @"completed"; | ||
93 | _barrierQueue = dispatch_queue_create("com.hackemist.SDWebImageDownloaderBarrierQueue", DISPATCH_QUEUE_CONCURRENT); | 79 | _barrierQueue = dispatch_queue_create("com.hackemist.SDWebImageDownloaderBarrierQueue", DISPATCH_QUEUE_CONCURRENT); |
94 | _downloadTimeout = 15.0; | 80 | _downloadTimeout = 15.0; |
95 | 81 | ||
96 | - _dnsFlag = [[NSUserDefaults standardUserDefaults] stringForKey:@"kUserConfigHttpDNS"]; | ||
97 | - | ||
98 | - [[HttpDnsService sharedInstance] setAccountID:160270]; | ||
99 | - [[HttpDnsService sharedInstance] setDelegateForDegradationFilter:(id<HttpDNSDegradationDelegate>)self]; | ||
100 | - [[HttpDnsService sharedInstance] setExpiredIPEnabled:YES]; | ||
101 | #if DEBUG | 82 | #if DEBUG |
102 | - [[HttpDnsService sharedInstance] setLogEnabled:YES]; | 83 | + _enableHttpDNS = YES; |
84 | +#else | ||
85 | + _enableHttpDNS = [[[NSUserDefaults standardUserDefaults] stringForKey:@"kUserConfigHttpDNS"] isEqualToString:@"2a90dfa0f37b92aaebf369e9a4d38ba4"]; | ||
103 | #endif | 86 | #endif |
104 | } | 87 | } |
105 | return self; | 88 | return self; |
@@ -142,99 +125,100 @@ static NSString *const kCompletedCallbackKey = @"completed"; | @@ -142,99 +125,100 @@ static NSString *const kCompletedCallbackKey = @"completed"; | ||
142 | - (id <SDWebImageOperation>)downloadImageWithURL:(NSURL *)url options:(SDWebImageDownloaderOptions)options progress:(SDWebImageDownloaderProgressBlock)progressBlock completed:(SDWebImageDownloaderCompletedBlock)completedBlock { | 125 | - (id <SDWebImageOperation>)downloadImageWithURL:(NSURL *)url options:(SDWebImageDownloaderOptions)options progress:(SDWebImageDownloaderProgressBlock)progressBlock completed:(SDWebImageDownloaderCompletedBlock)completedBlock { |
143 | __block SDWebImageDownloaderOperation *operation; | 126 | __block SDWebImageDownloaderOperation *operation; |
144 | __weak __typeof(self)wself = self; | 127 | __weak __typeof(self)wself = self; |
145 | - | ||
146 | - BOOL useAliDNS = NO; | ||
147 | - NSString *imageURLHost = url.host;//获取图片URL的host | ||
148 | - NSURL *newURL = url; | ||
149 | - if (imageURLHost.length > 0) { | ||
150 | - NSArray *ips = [[HttpDnsService sharedInstance] getIpsByHost:imageURLHost];//同步请求ip地址列表 | ||
151 | - if ([ips isKindOfClass:[NSArray class]] && [ips respondsToSelector:@selector(count)] && ips.count > 0) { | ||
152 | - NSString *ipAdress = [ips objectAtIndex:0]; | ||
153 | - NSString *urlString = [url absoluteString]; | ||
154 | - NSRange hostRange = [urlString rangeOfString:imageURLHost]; | ||
155 | - if (NSNotFound != hostRange.location) { | ||
156 | - useAliDNS = YES; | ||
157 | - NSString *convertedURLString = [urlString stringByReplacingCharactersInRange:hostRange withString:ipAdress];//host转换之后的urlstring | ||
158 | - newURL = [NSURL URLWithString:convertedURLString]; //替换原始url为转换后的值 | 128 | + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ |
129 | + BOOL useAliDNS = NO; | ||
130 | + NSString *imageURLHost = url.host;//获取图片URL的host | ||
131 | + NSURL *newURL = url; | ||
132 | + if (wself.enableHttpDNS && (imageURLHost.length > 0)) { | ||
133 | + NSArray *ips = [[HttpDnsService sharedInstance] getIpsByHostAsync:imageURLHost];//同步请求ip地址列表 | ||
134 | + if ([ips isKindOfClass:[NSArray class]] && [ips respondsToSelector:@selector(count)] && ips.count > 0) { | ||
135 | + NSString *ipAdress = [ips objectAtIndex:0]; | ||
136 | + NSString *urlString = [url absoluteString]; | ||
137 | + NSRange hostRange = [urlString rangeOfString:imageURLHost]; | ||
138 | + if ((NSNotFound != hostRange.location) && (ipAdress.length > 0)) { | ||
139 | + useAliDNS = YES; | ||
140 | + NSString *convertedURLString = [urlString stringByReplacingCharactersInRange:hostRange withString:ipAdress];//host转换之后的urlstring | ||
141 | + newURL = [NSURL URLWithString:convertedURLString]; //替换原始url为转换后的值 | ||
142 | + } | ||
159 | } | 143 | } |
160 | } | 144 | } |
161 | - } | ||
162 | 145 | ||
163 | - [self addProgressCallback:progressBlock andCompletedBlock:completedBlock forURL:url createCallback:^{ | ||
164 | - NSTimeInterval timeoutInterval = wself.downloadTimeout; | ||
165 | - if (timeoutInterval == 0.0) { | ||
166 | - timeoutInterval = 15.0; | ||
167 | - } | 146 | + [wself addProgressCallback:progressBlock andCompletedBlock:completedBlock forURL:url createCallback:^{ |
147 | + NSTimeInterval timeoutInterval = wself.downloadTimeout; | ||
148 | + if (timeoutInterval == 0.0) { | ||
149 | + timeoutInterval = 15.0; | ||
150 | + } | ||
168 | 151 | ||
169 | - // In order to prevent from potential duplicate caching (NSURLCache + SDImageCache) we disable the cache for image requests if told otherwise | ||
170 | - NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:newURL cachePolicy:(options & SDWebImageDownloaderUseNSURLCache ? NSURLRequestUseProtocolCachePolicy : NSURLRequestReloadIgnoringLocalCacheData) timeoutInterval:timeoutInterval]; | ||
171 | - request.HTTPShouldHandleCookies = (options & SDWebImageDownloaderHandleCookies); | ||
172 | - request.HTTPShouldUsePipelining = YES; | ||
173 | - if (wself.headersFilter) { | ||
174 | - request.allHTTPHeaderFields = wself.headersFilter(newURL, [wself.HTTPHeaders copy]); | ||
175 | - } | ||
176 | - else { | ||
177 | - request.allHTTPHeaderFields = wself.HTTPHeaders; | ||
178 | - } | ||
179 | - if (useAliDNS) { //如果使用了DNS功能,要设置httpheader的host字段的值,否则请求失败 | ||
180 | - [request setValue:imageURLHost forHTTPHeaderField:@"host"]; | ||
181 | - } | ||
182 | - operation = [[wself.operationClass alloc] initWithRequest:request | ||
183 | - options:options | ||
184 | - progress:^(NSInteger receivedSize, NSInteger expectedSize) { | ||
185 | - SDWebImageDownloader *sself = wself; | ||
186 | - if (!sself) return; | ||
187 | - __block NSArray *callbacksForURL; | ||
188 | - dispatch_sync(sself.barrierQueue, ^{ | ||
189 | - callbacksForURL = [sself.URLCallbacks[url] copy]; | ||
190 | - }); | ||
191 | - for (NSDictionary *callbacks in callbacksForURL) { | ||
192 | - SDWebImageDownloaderProgressBlock callback = callbacks[kProgressCallbackKey]; | ||
193 | - if (callback) callback(receivedSize, expectedSize); | 152 | + // In order to prevent from potential duplicate caching (NSURLCache + SDImageCache) we disable the cache for image requests if told otherwise |
153 | + NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:newURL cachePolicy:(options & SDWebImageDownloaderUseNSURLCache ? NSURLRequestUseProtocolCachePolicy : NSURLRequestReloadIgnoringLocalCacheData) timeoutInterval:timeoutInterval]; | ||
154 | + request.HTTPShouldHandleCookies = (options & SDWebImageDownloaderHandleCookies); | ||
155 | + request.HTTPShouldUsePipelining = YES; | ||
156 | + if (wself.headersFilter) { | ||
157 | + request.allHTTPHeaderFields = wself.headersFilter(newURL, [wself.HTTPHeaders copy]); | ||
158 | + } | ||
159 | + else { | ||
160 | + request.allHTTPHeaderFields = wself.HTTPHeaders; | ||
161 | + } | ||
162 | + if (useAliDNS) { //如果使用了DNS功能,要设置httpheader的host字段的值,否则请求失败 | ||
163 | + [request setValue:imageURLHost forHTTPHeaderField:@"Host"]; | ||
164 | + } | ||
165 | + operation = [[wself.operationClass alloc] initWithRequest:request | ||
166 | + options:options | ||
167 | + progress:^(NSInteger receivedSize, NSInteger expectedSize) { | ||
168 | + SDWebImageDownloader *sself = wself; | ||
169 | + if (!sself) return; | ||
170 | + __block NSArray *callbacksForURL; | ||
171 | + dispatch_sync(sself.barrierQueue, ^{ | ||
172 | + callbacksForURL = [sself.URLCallbacks[url] copy]; | ||
173 | + }); | ||
174 | + for (NSDictionary *callbacks in callbacksForURL) { | ||
175 | + SDWebImageDownloaderProgressBlock callback = callbacks[kProgressCallbackKey]; | ||
176 | + if (callback) callback(receivedSize, expectedSize); | ||
177 | + } | ||
194 | } | 178 | } |
195 | - } | ||
196 | - completed:^(UIImage *image, NSData *data, NSError *error, BOOL finished) { | ||
197 | -// NSLog(@"download image completed:url == %@,\nimage = %@",url,image); | ||
198 | - SDWebImageDownloader *sself = wself; | ||
199 | - if (!sself) return; | ||
200 | - __block NSArray *callbacksForURL; | ||
201 | - dispatch_barrier_sync(sself.barrierQueue, ^{ | ||
202 | - callbacksForURL = [sself.URLCallbacks[url] copy]; | ||
203 | - if (finished) { | ||
204 | - [sself.URLCallbacks removeObjectForKey:url]; | 179 | + completed:^(UIImage *image, NSData *data, NSError *error, BOOL finished) { |
180 | + // NSLog(@"download image completed:url == %@,\nimage = %@",url,image); | ||
181 | + SDWebImageDownloader *sself = wself; | ||
182 | + if (!sself) return; | ||
183 | + __block NSArray *callbacksForURL; | ||
184 | + dispatch_barrier_sync(sself.barrierQueue, ^{ | ||
185 | + callbacksForURL = [sself.URLCallbacks[url] copy]; | ||
186 | + if (finished) { | ||
187 | + [sself.URLCallbacks removeObjectForKey:url]; | ||
188 | + } | ||
189 | + }); | ||
190 | + for (NSDictionary *callbacks in callbacksForURL) { | ||
191 | + SDWebImageDownloaderCompletedBlock callback = callbacks[kCompletedCallbackKey]; | ||
192 | + if (callback) callback(image, data, error, finished); | ||
205 | } | 193 | } |
206 | - }); | ||
207 | - for (NSDictionary *callbacks in callbacksForURL) { | ||
208 | - SDWebImageDownloaderCompletedBlock callback = callbacks[kCompletedCallbackKey]; | ||
209 | - if (callback) callback(image, data, error, finished); | ||
210 | } | 194 | } |
211 | - } | ||
212 | - cancelled:^{ | ||
213 | - SDWebImageDownloader *sself = wself; | ||
214 | - if (!sself) return; | ||
215 | - dispatch_barrier_async(sself.barrierQueue, ^{ | ||
216 | - [sself.URLCallbacks removeObjectForKey:url]; | ||
217 | - }); | ||
218 | - }]; | ||
219 | - operation.shouldDecompressImages = wself.shouldDecompressImages; | ||
220 | - | ||
221 | - if (wself.username && wself.password) { | ||
222 | - operation.credential = [NSURLCredential credentialWithUser:wself.username password:wself.password persistence:NSURLCredentialPersistenceForSession]; | ||
223 | - } | ||
224 | - | ||
225 | - if (options & SDWebImageDownloaderHighPriority) { | ||
226 | - operation.queuePriority = NSOperationQueuePriorityHigh; | ||
227 | - } else if (options & SDWebImageDownloaderLowPriority) { | ||
228 | - operation.queuePriority = NSOperationQueuePriorityLow; | ||
229 | - } | 195 | + cancelled:^{ |
196 | + SDWebImageDownloader *sself = wself; | ||
197 | + if (!sself) return; | ||
198 | + dispatch_barrier_async(sself.barrierQueue, ^{ | ||
199 | + [sself.URLCallbacks removeObjectForKey:url]; | ||
200 | + }); | ||
201 | + }]; | ||
202 | + operation.shouldDecompressImages = wself.shouldDecompressImages; | ||
203 | + | ||
204 | + if (wself.username && wself.password) { | ||
205 | + operation.credential = [NSURLCredential credentialWithUser:wself.username password:wself.password persistence:NSURLCredentialPersistenceForSession]; | ||
206 | + } | ||
207 | + | ||
208 | + if (options & SDWebImageDownloaderHighPriority) { | ||
209 | + operation.queuePriority = NSOperationQueuePriorityHigh; | ||
210 | + } else if (options & SDWebImageDownloaderLowPriority) { | ||
211 | + operation.queuePriority = NSOperationQueuePriorityLow; | ||
212 | + } | ||
230 | 213 | ||
231 | - [wself.downloadQueue addOperation:operation]; | ||
232 | - if (wself.executionOrder == SDWebImageDownloaderLIFOExecutionOrder) { | ||
233 | - // Emulate LIFO execution order by systematically adding new operations as last operation's dependency | ||
234 | - [wself.lastAddedOperation addDependency:operation]; | ||
235 | - wself.lastAddedOperation = operation; | ||
236 | - } | ||
237 | - }]; | 214 | + [wself.downloadQueue addOperation:operation]; |
215 | + if (wself.executionOrder == SDWebImageDownloaderLIFOExecutionOrder) { | ||
216 | + // Emulate LIFO execution order by systematically adding new operations as last operation's dependency | ||
217 | + [wself.lastAddedOperation addDependency:operation]; | ||
218 | + wself.lastAddedOperation = operation; | ||
219 | + } | ||
220 | + }]; | ||
221 | + }); | ||
238 | 222 | ||
239 | return operation; | 223 | return operation; |
240 | } | 224 | } |
-
Please register or login to post a comment