完美解决SDWebImage加载多个图片内存崩溃的问题
SDWebImage大家肯定都恨熟悉了,國內(nèi)外太多的App使用其進(jìn)行圖片加載。
但是最近在使用過程中發(fā)現(xiàn),我用SDWebImage加載多個(gè)圖片,類似微博動(dòng)態(tài)那種,在加載的過程中。我發(fā)現(xiàn)當(dāng)圖片分辨率比較大的時(shí)候(不是圖片大),加載幾張圖片就崩潰了。
網(wǎng)上說可以每次加載圖片清空memcache,但是效果并不好。
[[SDImageCache sharedImageCache] setValue:nil forKey:@"memCache"];
也有說把使用下面這個(gè)方法的地方全部注掉
+ (UIImage *)decodedImageWithImage:(UIImage *)image?
但是效果并不明顯。同時(shí)加載5-7張高分辨率圖片還是會(huì)立即崩潰
我們使用SDWebimage肯定都會(huì)做三件事,一判斷本地是否有這張圖,二有的時(shí)候直接從本地取圖片,三沒有的時(shí)候去網(wǎng)絡(luò)下載。大概是像下面這樣
NSString *logoString = [_currentDic stringValueForKey:@"team_img"];if(logoString.length>0){[[SDImageCache sharedImageCache] queryDiskCacheForKey:logoString done:^(UIImage *image, SDImageCacheType cacheType) {if (image) {[_teamImage setImage:image];}else{[_teamImage sd_setImageWithURL:kNSUrl(logoString)placeholderImage:IMGNAMED(@"defaultAvatar2")options:SDWebImageRefreshCachedcompleted:^(UIImage *image, NSError *error, SDImageCacheType cacheType, NSURL *imageURL) {if (image) {[[SDImageCache sharedImageCache] storeImage:image forKey:logoString toDisk:YES];}}];}}];}
在內(nèi)部都會(huì)使用到下面這個(gè)方法 - (UIImage *)diskImageForKey:(NSString *)key {NSData *data = [self diskImageDataBySearchingAllPathsForKey:key];if (data) {UIImage *image = [UIImage sd_imageWithData:data];image = [self scaledImageForKey:key image:image];image = [UIImage decodedImageWithImage:image];return image;}else {return nil;} }
我發(fā)現(xiàn)這里 UIImage *image = [UIImage sd_imageWithData:data];
圖片取出來的時(shí)候就已經(jīng)巨大無比,占用了很大的內(nèi)存,導(dǎo)致內(nèi)存來不及釋放就崩潰。
抽絲剝繭我們進(jìn)入
sd_imageWithData方法發(fā)現(xiàn)這里面對(duì)圖片的處理是直接按照原大小進(jìn)行的,如果幾千是分辨率這里導(dǎo)致占用了大量?jī)?nèi)存。
所以我們需要在這里對(duì)圖片做一次等比的壓縮。
我們?cè)?/span>
UIImage+MultiFormat這個(gè)類里面添加如下壓縮方法,
+(UIImage *)compressImageWith:(UIImage *)image {float imageWidth = image.size.width;float imageHeight = image.size.height;float width = 640;float height = image.size.height/(image.size.width/width);float widthScale = imageWidth /width;float heightScale = imageHeight /height;// 創(chuàng)建一個(gè)bitmap的context// 并把它設(shè)置成為當(dāng)前正在使用的contextUIGraphicsBeginImageContext(CGSizeMake(width, height));if (widthScale > heightScale) {[image drawInRect:CGRectMake(0, 0, imageWidth /heightScale , height)];}else {[image drawInRect:CGRectMake(0, 0, width , imageHeight /widthScale)];}// 從當(dāng)前context中創(chuàng)建一個(gè)改變大小后的圖片UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();// 使當(dāng)前的context出堆棧UIGraphicsEndImageContext();return newImage;}再在上面箭頭代碼后面對(duì)圖片進(jìn)行壓縮#ifdef SD_WEBPelse if ([imageContentType isEqualToString:@"image/webp"]){image = [UIImage sd_imageWithWebPData:data];} #endifelse {image = [[UIImage alloc] initWithData:data];if (data.length/1024 > 128) {image = [self compressImageWith:image];}UIImageOrientation orientation = [self sd_imageOrientationFromImageData:data];if (orientation != UIImageOrientationUp) {image = [UIImage imageWithCGImage:image.CGImagescale:image.scaleorientation:orientation];}到了這里還需要進(jìn)行最后一步。就是 在SDWebImageDownloaderOperation的connectionDidFinishLoading方法里面的:
UIImage *image = [UIImage sd_imageWithData:self.imageData];
//將等比壓縮過的image在賦在轉(zhuǎn)成data賦給self.imageData
NSData *data = UIImageJPEGRepresentation(image, 1);
self.imageData = [NSMutableData dataWithData:data];
? ?再配合 ? ?[[SDImageCache sharedImageCache] setValue:nil forKey:@"memCache"];(圖片加載后使用)大功告成,親測(cè)內(nèi)存基本變化不大,自動(dòng)釋放也來得及。
總結(jié)
以上是生活随笔為你收集整理的完美解决SDWebImage加载多个图片内存崩溃的问题的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: vue项目打包后,favorite.ic
- 下一篇: Condition的使用