在iOS的请求网络图片框架中, [**SDWebImage**](https://github.com/rs/SDWebImage) 可谓是占据大半壁江山。它支持从网络中下载且缓存图片,并设置图片到对应的UIImageView控件或者UIButton控件。如在我们熟悉的UITableView中经常使用到:```/** * Integrates SDWebImage async downloading and caching of remote images with UIImageView. * * Usage with a UITableViewCell sub-class: * * @code#import...
- (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];
}
// Here we use the provided sd_setImageWithURL: method to load the web image
// Ensure you use a placeholder image otherwise cells will be initialized with no image
[cell.imageView sd_setImageWithURL:[NSURL URLWithString:@"http://example.com/image.jpg"]
placeholderImage:[UIImage imageNamed:@"placeholder"]];
cell.textLabel.text = @"My Text";
return cell;
}
* @endcode
*/
```
这样简单方便地在项目中使用SDWebImage来管理图片加载相关操作,可以极大地提高开发效率,让我们更加专注于业务逻辑实现。趁最近项目不忙,我闲下来研究其实现的过程,多读源码,更有助于提高自己的编码水平吧。
SDWebImage 流程
![SDWebImage流程图.png](https://img.haomeiwen.com/i1377007/c7e278abad7ecfed.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
以上是SDWebImage实现流程,具体我们从以上实例来解析:
1.入口setImageWithURL:placeholderImage:options:
![UIImageView设置图片.png](https://img.haomeiwen.com/i1377007/d02678b87a71b600.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
会先把 placeholderImage 显示,然后 SDWebImageManager 根据 URL 开始处理图片。这里值得注意的是,开始加载之前图片先取消对应的UIImageView先前的图片下载操作。试想,如果我们给UIImageView设置了一张新的图片,那么我们还会在意该UIImageVIew先前是要加载哪一张图片么?应该是不在意的吧!那是不是应该尝试把该UIImageView先前的加载图片相关操作给取消掉呢。
```
[self sd_cancelCurrentImageLoad];
```
2.执行到SDWebImageManagerdownloadWithURL:delegate:options:userInfo:,会先根据给定的URL生成一个唯一的Key,之后利用这个key到缓存中查找对应的图片缓存。若内存缓存中没有,则读取磁盘缓存,如果存在磁盘缓存,那么将磁盘缓存读到内存中成为内存缓存。如果都磁盘缓存也没有的话,那么就在执行的doneBlock中开始下载图片。
![读取缓存图片.png](https://img.haomeiwen.com/i1377007/d4610de3361977e3.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
![下载图片操作.png](https://img.haomeiwen.com/i1377007/2fba7eec2d43a525.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
3.图片下载由 NSURLConnection 来做,实现相关 delegate 来判断图片下载中、下载完成和下载失败。
![设置NSURLConnection对象.png](https://img.haomeiwen.com/i1377007/7fb8d287228d59c0.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)![NSURLConnection对象实现代理.png](https://img.haomeiwen.com/i1377007/023395e911b024af.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
4.connectionDidFinishLoading: 数据下载完成后交给 SDWebImageDecoder 做图片解码处理。
5.图片解码处理在一个 NSOperationQueue 完成,
不会拖慢主线程 UI。
6.在主线程 notifyDelegateOnMainThreadWithInfo:
宣告解码完成,
imageDecoder:didFinishDecodingImage:userInfo:
回调给 SDWebImageDownloader。就不一一截图了。
7.imageDownloader:didFinishWithImage:
回调给 SDWebImageManager 告知图片下载完成。
8.通知所有的 downloadDelegates 下载完成,
回调给需要的地方展示图片。
9.将图片保存到 SDImageCache 中,
内存缓存和硬盘缓存同时保存。
写文件到硬盘也在以单独 NSInvocationOperation 完成,
避免拖慢主线程。
10.SDImageCache 在初始化的时候会注册一些消息通知,
在内存警告或退到后台的时候清理内存图片缓存,
应用结束的时候清理过期图片。
11.SDWI 也提供了 UIButton+WebCache 和
MKAnnotationView+WebCache,方便使用。
22.SDWebImagePrefetcher 可以预先下载图片,
方便后续使用。
总结
SDWebImage作为一个优秀的图片加载框架,提供的使用方法和接口对开发者来说非常友好。其内部实现多是采用Block的方式来实现回调,代码阅读起来可能没有那么直观。本人能力有限,文章中难免有错误以及认识不到位的地方,若大家在阅读过程中有发现不合理或者错误的地方恳请在评论中指出,我会在第一时间进行修正,不胜感激。
。
网友评论