




已阅读5页,还剩9页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
对SDWebImage的浅分析SDWebImage源代码分析SDWebImage使用一个可管理远程图片加载的类库SDWebImage托管在github上。/rs/SDWebImage这个类库提供一个UIImageView类别以支持加载来自网络的远程图片。具有缓存管理、异步下载、同一个URL下载次数控制和优化等特征。将SDWebImage类库添加入工程时,一定注意需要添加MapKit.framework,如图所示,因为MKAnnotationView+WebCache.h依赖该framework。SDWebImage库的作用:通过对UIImageView的类别扩展来实现异步加载替换图片的工作。主要用到的对象:1、UIImageView (WebCache)类别,入口封装,实现读取图片完成后的回调2、SDWebImageManager,对图片进行管理的中转站,记录那些图片正在读取。向下层读取Cache(调用SDImageCache),或者向网络读取对象(调用SDWebImageDownloader)。实现SDImageCache和SDWebImageDownloader的回调。3、SDImageCache,根据URL的MD5摘要对图片进行存储和读取(实现存在内存中或者存在硬盘上两种实现)实现图片和内存清理工作。4、SDWebImageDownloader,根据URL向网络读取数据(实现部分读取和全部读取后再通知回调两种方式)其他类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 来判断图片下载中、下载完成和下载失败。1. connection:didReceiveData: 中利用 ImageIO做了按图片下载进度加载效果。2. connectionDidFinishLoading: 数据下载完成后交给 SDWebImageDecoder 做图片解码处理。3. 图片解码处理在一个 NSOperationQueue完成,不会拖慢主线程 UI。如果有需要对下载的图片进行二次处理,最好也在这里完成,效率会好很多。4. 在主线程 notifyDelegateOnMainThreadWithInfo: 宣告解码完成,imageDecoder:didFinishDecodingImage:userInfo: 回调给SDWebImageDownloader。5. imageDownloader:didFinishWithImage: 回调给 SDWebImageManager告知图片下载完成。6. 通知所有的 downloadDelegates下载完成,回调给需要的地方展示图片。7. 将图片保存到 SDImageCache中,内存缓存和硬盘缓存同时保存。写文件到硬盘也在以单独 NSInvocationOperation完成,避免拖慢主线程。8. SDImageCache在初始化的时候会注册一些消息通知,在内存警告或退到后台的时候清理内存图片缓存,应用结束的时候清理过期图片。9. SDWI 也提供了 UIButton+WebCache 和 MKAnnotationView+WebCache,方便使用。10. SDWebImagePrefetcher 可以预先下载图片,方便后续使用。使用示范的代码:1.UITableView使用UIImageView+WebCache类(基本应用,UIImageView的一个category)前提#import导入UIImageView+WebCache.h文件,然后在tableview的cellForRowAtIndexPath:方法下:1. #import UIImageView+WebCache.h 2.3. - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 4. 5. static NSString *MyIdentifier = MyIdentifier; 6.7. UITableViewCell *cell = tableView dequeueReusableCellWithIdentifier:MyIdentifier; 8.9. if (cell = nil) 10. 11. cell = UITableViewCell alloc initWithStyle:UITableViewCellStyleDefault 12. reuseIdentifier:MyIdentifier autorelease; 13. 14.15. / Here we use the new provided setImageWithURL: method to load the web image 16. cell.imageView setImageWithURL:NSURL URLWithString:/path/to/image.jpg 17. placeholderImage:UIImage imageNamed:placeholder.png; 18.19. cell.textLabel.text = My Text; 20. return cell; 21. 基本代码:1. imageView setImageWithURL:NSURL URLWithString:/path/image.jpg; 针对iOS4+目标平台,还可以使用如下块语句:1. / Here we use the new provided setImageWithURL: method to load the web image 2. cell.imageView setImageWithURL:NSURL URLWithString:/path/to/image.jpg 3. placeholderImage:UIImage imageNamed:placeholder.png 4. success:(UIImage *image) . success code here . 5. failure:(NSError *error) . failure code here .; 2. 使用SDWebImageManager类:可以进行一些异步加载的工作。1. SDWebImageManager *manager = SDWebImageManager sharedManager; 2. UIImage *cachedImage = manager imageWithURL:url; / 将需要缓存的图片加载进来 3. if (cachedImage) 4. / 如果Cache命中,则直接利用缓存的图片进行有关操作 5. / Use the cached image immediatly 6. else 7. / 如果Cache没有命中,则去下载指定网络位置的图片,并且给出一个委托方法 8. / Start an async download 9. manager downloadWithURL:url delegate:self; 10. 当然你的类要实现SDWebImageManagerDelegate协议,并且要实现协议的webImageManager:didFinishWithImage:方法。1. / 当下载完成后,调用回调方法,使下载的图片显示 2. - (void)webImageManager:(SDWebImageManager *)imageManager didFinishWithImage:(UIImage *)image 3. / Do something with the downloaded image 4. 3. 独立的异步图像下载可能会单独用到异步图片下载,则一定要用downloaderWithURL:delegate:来建立一个SDWebImageDownloader实例。1. downloader =SDWebImageDownloader downloaderWithURL:url delegate:self; 这样SDWebImageDownloaderDelegate协议的方法imageDownloader:didFinishWithImage:被调用时下载会立即开始并完成。4. 独立的异步图像缓存SDImageCache类提供一个创建空缓存的实例,并用方法imageForKey:来寻找当前缓存。1. UIImage*myCachedImage = SDImageCache sharedImageCache imageFromKey:myCacheKey; 存储一个图像到缓存是使用方法storeImage: forKey:1. SDImageCachesharedImageCache storeImage:myImage forKey:myCacheKey; 默认情况下,图像将被存储在内存缓存和磁盘缓存中。如果仅仅是想内存缓存中,要使用storeImage:forKey:toDisk:方法的第三个参数带一负值来替代。1.下载opertion类SDWebImageDownloaderOperationSDWebImageDownloaderOperation继承自NSOperation对外只暴漏了一个方法,两个属性它主要的功能是创建一个下载线程去下载图片,并保持回调的block待下载完成后进行对应的回调处理这里思想也比较清晰,下载和网络业务放在这里,与下载顺序(先进先出,先进后出)缓存逻辑,并发线程数量是独立的。唯独和外界有交叉的地方是下载开始和下载停止的两个通知,其发出去也是与业务无关的downloadOperation会创建一个NSUrlConnection,由其负责下载2.SDWebImageDownloader这个类负责管理下载operation它是个单例,负责管理并发下载operationqueuehttp的头部信息该类维护了一个由下载url作为key构成的可变字典key对应的value是一个数组,此处对应progress block和completedBlock也做了保存下载完整,下载失败等过程结束后,都会根据key在将其在可变字典里的记录移除掉由于这里的可变字典,可能会比较大,因为并发下载线程同时最多2个_downloadQueue.maxConcurrentOperationCount = 2;这里对字典的操作,都是互斥的,并且放在一个gcd线程里,_barrierQueue = dispatch_queue_create(com.hackemist.SDWebImageDownloaderBarrierQueue, DISPATCH_QUEUE_CONCURRENT);用dispatch_barrier_sync方式调用添加的时候,dispatch_barrier_sync(需要关注顺序)1. dispatch_barrier_sync(self.barrierQueue, 2. 3. BOOL first = NO; 4. if (!self.URLCallbacksurl) 5. 6. self.URLCallbacksurl = NSMutableArray.new; 7. first = YES; 8. 9.10. / Handle single download of simultaneous download request for the same URL 11. NSMutableArray *callbacksForURL = self.URLCallbacksurl; 12. NSMutableDictionary *callbacks = NSMutableDictionary.new; 13. if (progressBlock) callbackskProgressCallbackKey = progressBlock copy; 14. if (completedBlock) callbackskCompletedCallbackKey = completedBlock copy; 15. callbacksForURL addObject:callbacks; 16. self.URLCallbacksurl = callbacksForURL; 17.18. if (first) 19. 20. createCallback(); 21. 22. ); 移除的时候,dispatch_barrier_async(不需要关注顺序)1. dispatch_barrier_async(self.barrierQueue, 2. 3. self.URLCallbacks removeObjectForKey:url; 4. ); 这里用可变字典管理下载任务列表有另外一个好处,就是重复的下载请求可以避免核心代码如下:1. BOOL first = NO; 2. if (!self.URLCallbacksurl) 3. 4. self.URLCallbacksurl = NSMutableArray.new; 5. first = YES; 6. 7.8. . 9.10. if (first) 11. 12. createCallback(); 13. 3.SDImageCache 图片缓存这个类就管理缓存相关逻辑,本地硬盘缓存,内存缓存,内存告警时候的处理,图片过期处理,后台运行处理图片内存缓存是用NSCache来管理1. _memCache = NSCache alloc init; 图片硬盘存储是存储在library cache底下的子目录里,注意这个目录apple itunes备份是不保存的,放在这里最合理,图片太多图片写入到硬盘是放在一个serial queue里,一个线程顺序的写入到本地1. if (toDisk) 2. 3. dispatch_async(self.ioQueue, 4. 5. NSData *data = imageData; 6.7. if (!data) 8. 9. if (image) 10. 11. TARGET_OS_IPHONE 12. data = UIImageJPEGRepresentation(image, (CGFloat)1.0); 13. se 14. data = NSBitmapImageRep representationOfImageRepsInArray:image.representations usingType: NSJPEGFileType properties:nil; 15. dif 16. 17. 18.19. if (data) 20. 21. / Cant use defaultManager another thread 22. NSFileManager *fileManager = NSFileManager.new; 23.24. if (!fileManager fileExistsAtPath:_diskCachePath) 25. 26. fileManager createDirectoryAtPath:_diskCachePath withIntermediateDirectories:YES attributes:nil error:NULL; 27. 28.29. fileManager createFileAtPath:self defaultCachePathForKey:key contents:data attributes:nil; 30. 31. ); 32. 检查本地硬盘是否有缓存的图片,也是在这个queue里做的1. - (BOOL)diskImageExistsWithKey:(NSString *)key 2. 3. _block BOOL exists = NO; 4. dispatch_sync(_ioQueue, 5. 6. exists = _fileManager fileExistsAtPath:self defaultCachePathForKey:key; 7. ); 8.9. return exists; 10. 删除本地硬盘缓存图片文件:1. if (fromDisk) 2. 3. dispatch_async(self.ioQueue, 4. 5. NSFileManager defaultManager removeItemAtPath:self defaultCachePathForKey:key error:nil; 6. ); 7. 总之,涉及到IO操作的,都是单独的线程来做,这样总体来说用户体验是最佳的。4. app收到memory warning,app将要退出,以及app到后台运行各种状态下程序处理memory warning就是清空本地内存缓存1. NSNotificationCenter defaultCenter addObserver:self 2. selector:selector(clearMemory) 3. name:UIApplicationDidReceiveMemoryWarningNotification 4. object:nil; 这样可以尽早的释放内存中图片app将要退出的时候,可以清除本地硬盘上已经过期的图片(缓存时间可以任意指定),超过缓存size的图片(缓存size可以任意指定)app 在ios4.0之后可以放在后台运行一段时间以上的任务也可以放在后台运行一段时间1. - (void)backgroundCleanDisk 2. 3. UIApplication *application = UIApplication sharedApplication; 4. _block UIBackgroundTaskIdentifier bgTask = application beginBackgroundTaskWithExpirationHandler: 5. 6. / Clean up any unfinished task business by marking where you 7. / stopped or ending the task outright. 8. application endBackgroundTask:bgTask; 9. bgTask = UIBackgroundTaskInvalid; 10. ; 11.12. / Start the long-running task and return immediately. 13. dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), 14. 15. / Do the work associated with the task, preferably in chunks. 16. self cleanDisk; 17.18. application endBackgroundTask:bgTask; 19. bgTask = UIBackgroundTaskInvalid; 20. ); 21. 5.SDWebImageManager总体的image 管理类其对外暴露的接口返回的是id类型,实现了协议(id)返回出去其实是SDWebImageCombinedOperation它什么都不做,仅仅保存两个东西:(一个block,可以取消下载operation,一个operation,去查询本地硬盘缓存的operation)这样就很清晰了,这个对外返回的SDWebImageCombinedOperation,要么查到缓存,要么没查到,可以去下载,也可以取消下载SDWebImageCombinedOperation封装的很好,给用户看到的是透明的,对外可以找到缓存或者下载到图片,或者由用户决定取消下载图片6.下载回来的图片解压缩下载成功的图片会被解压缩,这样在图片渲染到屏幕上,可以比正常的二进制图片数据渲染减少一个步骤,可以提升体验具体在图片下载完整的时候,就在下载operation线程里,把这件事情做了在NSURLConnection的回调里可以看到1. - (void)connectionDidFinishLoading:(NSURLConnection *)aConnection 2. 3. CFRunLoopStop(CFRunLoopGetCurrent(); 4. self.
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 20年后的我作文800字10篇
- 养殖产业发展与购销合作契约
- 促进工资性收入合理增长实施方案
- 一个神奇的故事想象作文(6篇)
- 《鲁迅作品赏析:初中语文文学经典阅读教案》
- 房产交易完成产权归属证明书(6篇)
- 中小学语文成语故事分享教案
- 初中清明扫墓120词英语作文15篇范文
- 一年级写景小作文日落美景250字14篇
- 《中国古代文学流派简介:大一语文文学史教案》
- 海氏(hay)职位分析法-介绍、实践与评价合集课件
- 有趣的英汉互译-课件
- 洁净区空气洁净度级别空气悬浮粒子的标准规定表
- 人教版五年级下册期末语文试卷答题卡及答案
- 步进式加热炉耐材砌筑施工方案
- GB-T12232-2005- 通用阀门 法兰连接铁制闸阀
- 2022年中国电信店长技能四级认证教材
- (最新整理)《跨文化沟通》PPT课件
- 怎样分析日本气象传真图
- 常见散料堆积密度汇总-共10
- 视频监控巡查记录
评论
0/150
提交评论