SDWebImage 支持异步的图片下载+缓存,提供了 UIImageView+WebCacha 的 category,方便使用。使用SDWebImage首先了解它加载图片的流程。
  1. 入口 setImageWithURL:placeholderImage:options: 会先把 placeholderImage 显示,然后 SDWebImageManager 根据 URL 开始处理图片。
  2. 进入 SDWebImageManager-downloadWithURL:delegate:options:userInfo:,交给 SDImageCache 从缓存查找图片是否已经下载 queryDiskCacheForKey:delegate:userInfo:.
  3. 先从内存图片缓存查找是否有图片,如果内存中已经有图片缓存,SDImageCacheDelegate 回调 imageCache:didFindImage:forKey:userInfo: 到 SDWebImageManager。
  4. SDWebImageManagerDelegate 回调 webImageManager:didFinishWithImage: 到 UIImageView+WebCache 等前端展示图片。
  5. 如果内存缓存中没有,生成 NSInvocationOperation 添加到队列开始从硬盘查找图片是否已经缓存。
  6. 根据 URLKey 在硬盘缓存目录下尝试读取图片文件。这一步是在 NSOperation 进行的操作,所以回主线程进行结果回调 notifyDelegate:。
  7. 如果上一操作从硬盘读取到了图片,将图片添加到内存缓存中(如果空闲内存过小,会先清空内存缓存)。SDImageCacheDelegate 回调 imageCache:didFindImage:forKey:userInfo:。进而回调展示图片。
  8. 如果从硬盘缓存目录读取不到图片,说明所有缓存都不存在该图片,需要下载图片,回调 imageCache:didNotFindImageForKey:userInfo:。
  9. 共享或重新生成一个下载器 SDWebImageDownloader 开始下载图片。
  10. 图片下载由 NSURLConnection 来做,实现相关 delegate 来判断图片下载中、下载完成和下载失败。
  11. connection:didReceiveData: 中利用 ImageIO 做了按图片下载进度加载效果。
  12. connectionDidFinishLoading: 数据下载完成后交给 SDWebImageDecoder 做图片解码处理。
  13. 图片解码处理在一个 NSOperationQueue 完成,不会拖慢主线程 UI。如果有需要对下载的图片进行二次处理,最好也在这里完成,效率会好很多。
  14. 在主线程 notifyDelegateOnMainThreadWithInfo: 宣告解码完成,imageDecoder:didFinishDecodingImage:userInfo: 回调给 SDWebImageDownloader。
  15. imageDownloader:didFinishWithImage: 回调给 SDWebImageManager 告知图片下载完成。
  16. 通知所有的 downloadDelegates 下载完成,回调给需要的地方展示图片。
  17. 将图片保存到 SDImageCache 中,内存缓存和硬盘缓存同时保存。写文件到硬盘也在以单独 NSInvocationOperation 完成,避免拖慢主线程。
  18. SDImageCache 在初始化的时候会注册一些消息通知,在内存警告或退到后台的时候清理内存图片缓存,应用结束的时候清理过期图片。
  19. SDWI 也提供了 UIButton+WebCache 和 MKAnnotationView+WebCache,方便使用。
  20. SDWebImagePrefetcher 可以预先下载图片,方便后续使用
 
SDWebImage的案例1:在tableView中使用SDWebImage
#import <SDWebImage/UIImageView+WebCache.h>

...

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *MyIdentifier = @"MyIdentifier"; UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:MyIdentifier]; if (cell == nil)
{
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:MyIdentifier] autorelease];
} // Here we use the new provided sd_setImageWithURL: method to load the web image
[cell.imageView sd_setImageWithURL:[NSURL URLWithString:@"http://www.domain.com/path/to/image.jpg"]
placeholderImage:[UIImage imageNamed:@"placeholder.png"]];
  
cell.textLabel.text = @"My Text";
return cell;
}

The SDWebImageManager is the class behind the UIImageView+WebCache category. It ties the asynchronous downloader with the image cache store. You can use this class directly to benefit from web image downloading with caching in another context than a UIView (ie: with Cocoa).

 NSURL *url = [NSURL URLWithString:@"http://127.0.0.1/userManager/0.png"];
//SDWebImageManager管理器继承与UIImageView+WedCache。已异步的方式进行下载图片到缓冲区。
SDWebImageManager *manager = [SDWebImageManager sharedManager];
[manager downloadImageWithURL:url options: progress:^(NSInteger receivedSize, NSInteger expectedSize) {
NSLog(@"%ld,%ld",receivedSize,expectedSize);
}
completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, BOOL finished, NSURL *imageURL) {
//为imageView设置图片为下载的图片
[self.imageView setImage:image];
//打印图片的来源
NSLog(@"%@",imageURL);
}];

It's also possible to use the async image downloader independently:

[SDWebImageDownloader.sharedDownloader downloadImageWithURL:imageURL
options:
progress:^(NSInteger receivedSize, NSInteger expectedSize)
{
// progression tracking code
}
completed:^(UIImage *image, NSData *data, NSError *error, BOOL finished)
{
if (image && finished)
{
// do something with image
}
}];

在自己的案例中使用SDWebImage代码段:

添加自定义的只读缓存路径,其中这是可选的,如果没有指定,系统会默认
#import "SDWebImage/SDImageCache.h"
#import "AppDelegate.h"
......
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
//添加自定义的只读缓存路径:可选的
NSString *bundledPath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:@"CustomPathImages"];
[[SDImageCache sharedImageCache] addReadOnlyCachePath:bundledPath];
......
}

在使用缓存时,如果内存不够使用时,需要进行清理以释放内存。

#import "MasterViewController.h"
#import "SDWebImage/UIImageView+WebCache.h"
......
//清理缓存,
- (void)flushCache
{
/**
* 1、SDImageCache是怎么做数据管理的?
SDImageCache分两个部分,一个是内存层面的,一个是硬盘层面的。
内存层面的相当是个缓存器,以Key-Value的形式存储图片。
*/
//清理内存缓存
[SDWebImageManager.sharedManager.imageCache clearMemory];
//清理硬盘缓存
[SDWebImageManager.sharedManager.imageCache clearDisk];
}
//支持屏幕旋转
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
}
......

//为了显示大图片,替将连接中small替换成source;

NSString *largeImageURL = [[_objects objectAtIndex:indexPath.row] stringByReplacingOccurrencesOfString:@"small" withString:@"source"];

......

 

仪表器的使用方法。

#import "DetailViewController.h"
#import "SDWebImage/UIImageView+WebCache.h"
......
- (void)configureView
{
if (self.imageURL) {
//创建仪表器
__block UIActivityIndicatorView *activityIndicator;
//为防止循环引用问题,所以在block中使用imageView时要设置成弱引用,imageView中使用block,在block中如果再调用imageView时,不设置为弱引用,会出现循环引用问题。
__weak UIImageView *weakImageView = self.imageView;
[self.imageView sd_setImageWithURL:self.imageURL
placeholderImage:nil
options:SDWebImageProgressiveDownload
progress:^(NSInteger receivedSize, NSInteger expectedSize) {
//检测是否已经存在啦!,如果没有在新创建出一个
if (!activityIndicator) {
//将新创建的仪表器添加到imageView视图中
[weakImageView addSubview:activityIndicator = [UIActivityIndicatorView.alloc initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray]];
activityIndicator.center = weakImageView.center;
//开启动画,转吧!小宇宙
[activityIndicator startAnimating];
}
}
completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, NSURL *imageURL){
//将仪表器从imageView视图中进行删除
[activityIndicator removeFromSuperview];
activityIndicator = nil;
}];
}
}
......

在Cell中使用异步图片下载。

#import "MasterViewController.h"
#import "SDWebImage/UIImageView+WebCache.h"
......
/**
* 参数解析:
1.获取图片的路径
2.设置占位图片
3.options选项:当indexPath.row为0时,执行 SDWebImageRefreshCached:刷新缓存
*/
[cell.imageView sd_setImageWithURL:[NSURL URLWithString:[_objects objectAtIndex:indexPath.row]]
placeholderImage:[UIImage imageNamed:@"placeholder"] options:indexPath.row == ? SDWebImageRefreshCached : ];
......

在上段代码中,有如下两行代码:

__weak UIImageView *weakImageView = self.imageView;

__block UIActivityIndicatorView *activityIndicator;

其中第一条为了避免循环引用问题,加上了__weak,第二条使用了block。现在补充一下循环引用、block的知识点:

循环引用
  所有的引用计数系统,都存在循环应用的问题。例如下面的引用关系:
     1)对象a创建并引用到了对象b.
     2)对象b创建并引用到了对象c.
     3)对象c创建并引用到了对象b.
  这时候b和c的引用计数分别是2和1。当a不再使用b,调用release释放对b的所有权,因为c还引用了b,所以b的引用计数为1,

  b不会被释放。b不释放,c的引用计数就是1,c也不会被释放。从此,b和c永远留在内存中。这种情况,必须打断循环引用

  通过其他规则来维护引用关系。比如,我们常见的delegate往往是assign方式的属性而不是retain方式 的属性,

  赋值不会增加引用计数,就是为了防止delegation两端产生不必要的循环引用。如果一个UITableViewController对象a

  通过retain获取了UITableView对象b的所有权,这个UITableView对象b的delegate又是a,如果这个delegate是retain方式的,

  那基本上就没有机会释放这两个对象了。自己在设计使用delegate模式时,也要注意这点。

Block

  是可以获取其他函数局部变量的匿名函数,其不但方便开发,并且可以大幅提高应用的执行效率(多核心CPU可直接处理Block指令),如果希望进行修改局部变量的值,可以在定义局部变量之前使用__block。

iOS_SDWebImage框架分析的更多相关文章

  1. Android/Linux下CGroup框架分析及其使用

    1 cgroup介绍 CGroup是control group的简称,它为Linux kernel提供一种任务聚集和划分的机制,可以限制.记录.隔离进程组(process groups)所使用的资源( ...

  2. 几款开源的hybird移动app框架分析

    几款开源的Hybrid移动app框架分析 Ionic Onsen UI 与 ionic 相比 jQuery Mobile Mobile Angular UI 结论 很多移动开发者喜欢使用原生代码开发, ...

  3. 深入浅出 - Android系统移植与平台开发(十一) - Sensor HAL框架分析之一

    作者:唐老师,华清远见嵌入式学院讲师. 1. Sensor的概念 Sensor即传感器,在当前智能手机上大量存在:G-Sensor.LightsSensor. ProximitySensor.Temp ...

  4. 深入浅出 - Android系统移植与平台开发(八)- HAL Stub框架分析

    作者:唐老师,华清远见嵌入式学院讲师. 1. HAL Stub框架分析 HAL stub的框架比较简单,三个结构体.两个常量.一个函数,简称321架构,它的定义在:@hardware/libhardw ...

  5. openwrt: Makefile 框架分析

    openwrt: Makefile 框架分析 原文链接:blog.chinaunix.net/uid-26675482-id-4704952.html 本篇的主要目的是想通过分析Makefile,了解 ...

  6. Android 核心分析 之六 IPC框架分析 Binder,Service,Service manager

    IPC框架分析 Binder,Service,Service manager 我首先从宏观的角度观察Binder,Service,Service Manager,并阐述各自的概念.从Linux的概念空 ...

  7. VS2010/MFC编程入门之四(MFC应用程序框架分析)

    VS2010/MFC编程入门之四(MFC应用程序框架分析)-软件开发-鸡啄米 http://www.jizhuomi.com/software/145.html   上一讲鸡啄米讲的是VS2010应用 ...

  8. Yii PHP 框架分析(二)

    Yii PHP 框架分析(二)作者:wdy http://hi.baidu.com/delphiss/blog/item/54597af595085ad3f3d38552.html Yii是基于组件( ...

  9. Yii PHP 框架分析 (一)

    Yii PHP 框架分析 (一)作者:wdy http://hi.baidu.com/delphiss/blog/item/f7da86d787adb72506088b4b.html 基于yii1.0 ...

随机推荐

  1. 004androidStudio ndk开发环境

    004androidStudio ndk开发环境 android studio中编译C/C++源代码 1. 配置ndk.dir 在 local.properties 添加如下配置: sdk.dir=p ...

  2. python静态网页爬虫之xpath

    常用语句: 1.starts-with(@属性名称,属性字符相同部分)使用情形: 以相同的字符开头 <div id = 'test-1'>需要的内容1</div> <di ...

  3. yii2 刷新缓存(刷新模型缓存)

    Yii2开启表结构缓存,因为当运用模型(model)时,AR的一些公共属性都会从DB中获取,这样会导致服务器负担一些额外的资源开销,实际上对于成品来说,服务器这些开始销是多余的,故应该阻止这种默认行为 ...

  4. PHP实现对短信验证码发送次数的限制(防机刷验证码)

    PHP实现对短信验证码发送限制(防止机刷验证码) 对用户获取短信验证码的手机号.ip.和浏览器(使用唯一标识)进行限制.本文介绍的方法是对用户每天只能通过同一浏览器或同一ip地址获取验证码10次或者同 ...

  5. Oracle Delete与系统资源

    在用Delete删除数据时,SQL语句首先要通过全表扫描或索引扫描找到符合条件的记录并删除. 然而在这个过程中将消耗大量的CPU资源,I/O资源以及UNDO数据. 如果删除的数据量较大,将极大的影响系 ...

  6. MVC路由自定义及视图找寻规则

    这篇关于MVC路由及视图规则本来是昨天要发的,但是本人真的有点懒,终于今天忍无可忍了.初学MVC的时候比现在还菜一点(现在也很菜),想着会用就行,但是有时还是会好奇,为什么它能找到控制器?为什么控制器 ...

  7. 注册Asp4.0到iis

  8. Consul文档收藏

    英文:https://www.consul.io/intro/getting-started/install.html 中文:http://www.liangxiansen.cn/2017/04/06 ...

  9. 浅析 Pycharm 内存、cpu 占用率

    浅析 Pycharm  内存.cpu 占用率 本机配置参数: ------------------------------------------ Windows 10 专业版   X64 ----- ...

  10. Python操作Redis(一)

    redis是一个key-value存储系统.和Memcached类似,它支持存储的value类型相对更多,包括string(字符串).list(链表).set(集合).zset(sorted set ...