程序员

如何正确”打开”SDWebImage框架

文艺求关注.png
  • SDWebImage托管在github上。https://github.com/rs/SDWebImage
  • 相信大家对SDWebImage这个库并不陌生,这个库提供一个UIImageView类别,以支持加载来自网络的远程图片。具有缓存管理异步下载、同一个URL下载次数控制优化等特征。
  • SDWebImage(新版本在各方法前加上了sd_前缀,以区分UIImageView+AFNetworking中的方法)
  • SDWebImage库的作用
    • 通过对UIImageView的类别扩展来实现异步加载替换图片的工作。
    • 主要用到的对象:

      • 1、UIImageView (WebCache)类别,入口封装,实现读取图片完成后的回调
      • 2、SDWebImageManager,对图片进行管理的中转站,记录那些图片正在读取。
        向下层读取Cache(调用SDImageCache),或者向网络读取对象(调用SDWebImageDownloader) 。
        实现SDImageCache和SDWebImageDownloader的回调。
      • 3、SDImageCache,根据URL的MD5摘要对图片进行存储和读取(实现存在内存中或者存在硬盘上两种实现)
        实现图片和内存清理工作。
      • 4、SDWebImageDownloader,根据URL向网络读取数据(实现部分读取和全部读取后再通知回调两种方式)

      • 其他类:
        SDWebImageDecoder,异步对图像进行了一次解压⋯⋯


不多说,接下来,直接上代码:

  • SDWebImage的基本使用
    • 需要下图片且需要获取下载进度
#import "UIImageView+WebCache.h"
// 内部会自动做 内存缓存 & 磁盘缓存
- (void)downloadImage1 {
    /**
     @param NSURL 下载图片的url地址
     @param UIImage 占位符号
     @param SDWebImageOptions 选项:枚举
        SDWebImageRetryFailed: 默认情况下,如果一个URL在下载的时候失败了,那么这个URL会被加入黑名单,不会尝试再次下载,如果使用该参数,则该URL不会被添加到黑名单中,意味着会对下载失败URL尝试从新下载/此标记取消黑名单
        SDWebImageLowPriority: //低优先级/默认情况下,在UI交互时也会启动图像下载,此标记则为取消这一特征/会退出到滚动试图停止滚动之后再继续下载图片/备注:NSURLConnection的网络下载事件监听的运行循环模式是 NSDefaultRunLoopMode
        SDWebImageCacheMemoryOnly: 使用该参数,将禁止磁盘缓存,只做内存缓存
        SDWebImageProgressiveDownload: //渐进式下载/此标记允许渐进式下载,就像浏览器中那样,下载过程中,图像会逐步显示出来/默认情况下,图像会在下载完成后一次性显示
        SDWebImageRefreshCached: //刷新缓存/遵守HTTP相应的缓存控制,如果需要,从远程刷新图像/磁盘缓存将有NSURLCache处理,而不是SDWebImage,这会对性能有轻微的影响/此选项用于处理URL指向图片发生改变的情况/如果缓存的图像被刷新,会调用一次completion block,并传递最终的图像
        SDWebImageContinueInBackground: //后台下载/如果系统版本是iOS 4+,那么当App进入后台后仍然会继续下载图像/这是想系统请求额外的后台时间保证下载请求完成的/如果后台任务过时,请求将会被取消
        SDWebImageHandleCookies: 通过设置,处理保存在NSHTTPCookieStore中的cookie
        SDWebImageAllowInvalidSSLCertificates: 允许不信任的SSL证书/可以出于测试目的的使用,在正式产品中慎用
        SDWebImageHighPriority: // 高优先级(优先下载)/默认情况下,图像会按照添加到队列中的顺序被加载,此标记会将它们移动到队列前端被立即加载/而不是等待当前队列被加载,因为等待队列加载会需要一段时间
        SDWebImageDelayPlaceholder: //延迟占位图片/默认情况下,在加载图像时,占位图片已经会被加载/此标记会延迟加载占位图像,直到图像已经完成加载
        SDWebImageTransformAnimatedImage: //转换动画图像/通常不会在科动画的图像上调用transformDownloadImage代理方法,因为大多数转换代码会破坏动画文件/使用此标记尝试转换
        SDWebImageAvoidAutoSetImage: //手动设置图像/下载完成后手动设置图片,默认是下载完成后自动放到ImageView上
     @param progress^ 进度回调
        receivedSize: 已经下载的数据大小
        expectedSize: 需要下载图片的总大小
     @param completed^ 图片下载完成会来到此block块
        image: 要下载的图片
        error: 错误信息
        *cacheType: 缓存类型
        imageURL: 图片URL
     */
    [self.imageView sd_setImageWithURL:[NSURL URLWithString:@"http://www.33lc.com/soft/UploadPic/2012-8/20128179452663218.jpg"] placeholderImage:[UIImage imageNamed:@""] options:0 progress:^(NSInteger receivedSize, NSInteger expectedSize) {
        NSLog(@"---%f-----------", 1.0 * receivedSize / expectedSize);
    } completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, NSURL *imageURL) {
        // 先做内存缓存,在做磁盘缓存
        switch (cacheType) {
            case SDImageCacheTypeNone:
                NSLog(@"直接从网络下载");
                break;
            case SDImageCacheTypeDisk:
                NSLog(@"从磁盘缓存");
                break;
            case SDImageCacheTypeMemory:
                NSLog(@"从内存缓存");
                break;
            default:
                break;
        }
    }];
    NSLog(@"%@", [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject]);   //答应当前存储路径
}

  • 只需要简单获得一张图片,不进行设置
#import "SDWebImageManager.h"
// 内部会自动做 内部缓存 & 磁盘缓存
- (void)downloadImage2 {
    // 最核心的方法
    [[SDWebImageManager sharedManager] downloadImageWithURL:[NSURL URLWithString:@"http://www.33lc.com/soft/UploadPic/2012-8/20128179452663218.jpg"] options:0 progress:^(NSInteger receivedSize, NSInteger expectedSize) {
        NSLog(@"---%f------------", 1.0 * receivedSize / expectedSize);
    } completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, BOOL finished, NSURL *imageURL) {
        self.imageView.image = image;
    }];
}

  • 不需要做任何缓存
#import "SDWebImageDownloader.h"
// 没有做任何缓存处理
// 最底层的方法
- (void)downloadImage3 {
    // data:图片的二进制数据
    [[SDWebImageDownloader sharedDownloader] downloadImageWithURL:[NSURL URLWithString:@"http://www.33lc.com/soft/UploadPic/2012-8/20128179452663218.jpg"] options:0 progress:^(NSInteger receivedSize, NSInteger expectedSize) {
    } completed:^(UIImage *image, NSData *data, NSError *error, BOOL finished) {

        // 此方法并没有做线程间通信操作,需手动添加线程间通信
        [[NSOperationQueue mainQueue] addOperationWithBlock:^{
            self.imageView.image = image;
        }];
    }];
}

  • 播放gif图片
#import "UIImage+GIF.h"
@property (weak, nonatomic) IBOutlet UIImageView *imageView;
- (void)playGif {
    // gif图片存在于资源库
    UIImage *image = [UIImage sd_animatedGIFNamed:@"dog"];
    self.imageView.image = image;
}

  • SDWebImage其他使用
// 当发生内存警告时会调用此方法
- (void)applicationDidReceiveMemoryWarning:(UIApplication *)application {
    // 1.清空缓存
    // clearDisk: 直接删除,然后从新重新创建
    // cleanDisk: 清除过期缓存,计算当前缓存的大小,和设置的最大缓存数量比较,如果超出那么会继续删除(删除方法:按照文件创建的先后顺序)/过期缓存:7天(60*60*24*7)
    [[SDWebImageManager sharedManager].imageCache cleanDisk];
    // 2.取消当前所有操作
    [[SDWebImageManager sharedManager] cancelAll];
    // 3.最大并发数量 == 6 (SDWebImageDownLoader: maxConcurrentOperationCount <在init方法中>);
    // 4.缓存文件的保存名称如何处理?拿到图片地址,然后对该路径进行md5加密,
    //      "补充":如何在命令行进行md5加密:echo -n "需要加密的内容" |md5
    // 5.该框架内部对内存警告的处理方式?内部通过监听通知的方法清理缓存 (SDWebImageCache - )
    // 6.该框架进行缓存处理的方式:可变字典(以前) ---> NSCache(现在)
    // 7.如何判断图片的类型: 在判断图片类型的时候,只匹配第一个字节(NSData+ImageContentType: sd_contentTypeForImageData)
    // 8.队列中任务的处理方式: FIFO: 先进先出(是一个枚举值,可以手动设置: SDWebImageDownLoader - _executionOrder = LIFO:后进先出)
    // 9.如何下载图片的?发送网络请求下载图片,NSURLConnection (SDWebImageDownloaderOperation)
    // 10.请求超时的时间: 15秒钟的时间
}

  • SDWebImage解惑
    • SDImageCache是怎么做数据管理的?
      • SDImageCache分两个部分,一个是内存层面的,一个是硬盘层面的
      • 内存层面的相当是个缓存器,以Key-Value的形式存储图片。当内存不够的时候会清除所有缓存图片。用搜索文件系统的方式做管理,文件替换方式是以时间为单位,剔除时间大于一周的图片文件。
      • 当SDWebImageManager向SDImageCache要资源时,先搜索内存层面的数据,如果有直接返回,没有的话去访问磁盘,将图片从磁盘读取出来,然后做Decoder,将图片对象放到内存层面做备份,再返回调用层.
    • 为啥必须做Decoder


  • 补充知识- 位移枚举简单介绍
    • 第一种枚举写法
typedef enum {
    VtcDemoTypeTop,
    VtcDemoTypeBottom,
}VtcDemoType;
  • 第二种枚举写法,定义类型
typedef NS_ENUM(NSInteger, VtcType) {
    VtcTypeTop,
    VtcTypeBottom,
};
  • 第三种枚举写法,按位枚举
// 一个参数可以传递多个值
// 如果是位移枚举,观察第一个枚举值,如果该枚举值 != 0 那么可以默认传0做参数,如果传0做参数,那么效率更高
typedef NS_OPTIONS(NSInteger, VtcActionType) {
    VtcActionTypeTop = 1<<0,    //1*2(0) = 1
    VtcActionTypeBottom = 1<<1, //1*2(1) = 2
    VtcActionTypeleft = 1<<2,   //1*2(2) = 4
    VtcActionTypeRight = 1<<3,  //1*2(3) = 8
};
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {

    [self demo:VtcActionTypeTop | VtcActionTypeRight | VtcActionTypeBottom | VtcActionTypeleft];
}
//按位与 & 1&1==1 1&0==0 0&0==0 只要有0则为0
//按位或 | 1|1==1 1|0==0 0|0==0 只要有1则为1
- (void)demo:(VtcType)type {
    if (type & VtcActionTypeTop) {
        NSLog(@"向上------%zd", type & VtcActionTypeTop);
    }
    if (type & VtcActionTypeleft) {
        NSLog(@"向左------%zd", type & VtcActionTypeleft);
    }
    if (type & VtcActionTypeBottom) {
        NSLog(@"向下------%zd", type & VtcActionTypeBottom);
    }
    if (type & VtcActionTypeRight) {
        NSLog(@"向右------%zd", type & VtcActionTypeRight);
    }
}

// so,options:可以传0;即效率最高,也可以使用按位或()传多个枚举,
[self.imageView sd_setImageWithURL:[NSURL URLWithString:@"http://www.33lc.com/soft/UploadPic/2012-8/20128179452663218.jpg"] placeholderImage:[UIImage imageNamed:@""] options:0 progress:^(NSInteger receivedSize, NSInteger expectedSize) {
        NSLog(@"---%f-----------", 1.0 * receivedSize / expectedSize);
    } completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, NSURL *imageURL) {
        // 先做内存缓存,在做磁盘缓存
        switch (cacheType) {
            case SDImageCacheTypeNone:
                NSLog(@"直接从网络下载");
                break;
            case SDImageCacheTypeDisk:
                NSLog(@"从磁盘缓存");
                break;
            case SDImageCacheTypeMemory:
                NSLog(@"从内存缓存");
                break;
            default:
                break;
        }
    }];

关注一下又不会怀孕.png

发表评论