A image downloader

应用场景,屏幕上只有一个Imageview,你只有一堆图片的url地址。需求:有个按钮点了以后,要快速切换到下一张图片。

这时候用SDWebImage的”UImageView+WebCache”是不是感觉有点捉急了,他TM还要一张张的加载。这里我们要的效果是,我在看某张图片的时候,后面的几张也给我TM加载好,就算没有加载好,我切过去的时候也给我显示一个进度条啊。

我的ImageDownloader的思路是:

1、既然有一组url地址,那就先给我吧,我直接去开始加载了。针对每个operation,加载完后就把value:图片 key:url地址 存到我这个singleton的NSCache里

- (void)startDownloadImagesWithURLArray:(NSArray *)urlstrArray
{
    for (NSString *str in urlstrArray) {
        if (str.length > 0) {
            [self enqueueOperationWithStr:str];
        }
    }
}

- (void)enqueueOperationWithStr:(NSString *)str
{
    NSMutableURLRequest *req = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:str] cachePolicy:NSURLCacheStorageAllowed timeoutInterval:8.0];
    ILSMLWebImageDownloaderOperation *op = [[ILSMLWebImageDownloaderOperation alloc] initWithRequest:req queue:self.workingQueue];
    [self.downloadQueue addOperation:op];

    op.completedBlock = ^(UIImage *image, NSData *data, NSError *error, BOOL finished) {
        if (!error) {
            MYLog(@"ILSMLImageDownloader is cache image for url %@", str);
            [self.dlCache setObject:image forKey:str];
        }else {
            MYLog(@"ILSMLWebImageDownloaderOperation download image error occured %@", error);
        }
    };

    if (!self.blocksDic[str]) {
        self.blocksDic[str] = op;
    }
}

2、外部接口就提供,你直接根据你的url地址来获取我这个singleton里cache的图片吧,如果我还没cache吧,那么我就告诉你,我现在的进度progressBlock,另外,一但我加载完,我也会告诉你的哦,compeletionBlock

- (UIImage *)imageForUrl:(NSString *)imageURLStr progressBlock:(SDWebImageDownloaderProgressBlock)progressBlock compeletionBlock:(SDWebImageDownloaderCompletedBlock)compeletionBlock
{
    UIImage *cacheImage = [self.dlCache objectForKey:imageURLStr];
    if (!cacheImage) {
        ILSMLWebImageDownloaderOperation *op = self.blocksDic[imageURLStr];
        if (op) {
            if (progressBlock) {
                op.progressBlock = ^(NSUInteger receivedSize, long long expectedSize) {
                    progressBlock(receivedSize, expectedSize);
                };
            }

            if (compeletionBlock) {
                op.completedBlock = ^(UIImage *image, NSData *data, NSError *error, BOOL finished) {
                    if (!error) {
                        [self.dlCache setObject:image forKey:imageURLStr];
                    }
                compeletionBlock(image, data, error, finished);
                };
            }
        }else {
            MYLog(@"ILSMLImageDownloader operation block does not exist");
        }
    }
    return cacheImage;
}

3、做男人当然要做一个有责任心的男人,既然你和它没关系了,那let it free吧。所以第三个接口就是清理掉不用的image

- (void)removeImageWithURLStr:(NSString *)imageURLStr
{
    ILSMLWebImageDownloaderOperation *op = self.blocksDic[imageURLStr];
    [op cancel];
    [self.blocksDic removeObjectForKey:imageURLStr];
    [self.dlCache removeObjectForKey:imageURLStr];
}

具体的使用例子:

- (void)loadImageData
{
    if (self.mediaDicArray.count == 0) {
        [[ILSINSNewInsatgramApi sharedInstance] otherUserDownloadMeidaWithCursor:self.currentCusor
                                                                          userId:@"203560" compeletionHandler:^(NSArray *mediaDicArray, NSString *nextCusor, NSError *error)
         {

             if (!error) {
                 [self.mediaDicArray addObjectsFromArray:mediaDicArray];

                 NSMutableArray *mArray = [NSMutableArray arrayWithCapacity:mediaDicArray.count];
                 for (id obj in mediaDicArray) {
                     [mArray addObject:[obj valueForKeyPath:@"images.low_resolution.url"]];
                 }
                 [[ILSMLImageDownloader sharedDownloader] startDownloadImagesWithURLArray:mArray];

                 self.currentCusor = nextCusor;
                 [self customImage];
             }
         }];
    }else {
        [self customImage];
    }
}

- (void)customImage
{
    NSString *path = [self.mediaDicArray[0] valueForKeyPath:@"images.low_resolution.url"];

    UIImage *result = [[ILSMLImageDownloader sharedDownloader] imageForUrl:path progressBlock:^(NSUInteger receivedSize, long long expectedSize) {
        MYLog(@"-----ILSMLEarnCoinsViewController is loading is %d  total is %llu", receivedSize, expectedSize);
    } compeletionBlock:^(UIImage *image, NSData *data, NSError *error, BOOL finished) {
        MYLog(@"-----ILSMLEarnCoinsViewController is compeletion");
        self.currentImageView.image = image;
    }];

    self.currentImageView.image = result;
}

- (void)skip:(id)sender
{
    if (self.mediaDicArray.count > 0) {
        NSString *path = [self.mediaDicArray[0] valueForKeyPath:@"images.low_resolution.url"];
        [[ILSMLImageDownloader sharedDownloader] removeImageWithURLStr:path];
        [self.mediaDicArray removeObjectAtIndex:0];
    }
    [self loadImageData];
}

记录一下最近吧,昨天早上被指派了一个新项目,自己iOS端逻辑今天全弄好了(过段时间整理下Instagram objc的API,open source出来),下午贴图。再过几天,等服务器端同事接口写好,我再花个两天,测试再花个几天,下周估计就能上线了。这个鸡巴项目叫morelikers。我们app扮演了一个”拉皮条“的角色。

下下周,中秋, lonely alone 去北京感受一下。