解析SDWebImage框架和RunLoop

来源:互联网 发布:刀塔传奇英雄数据 编辑:程序博客网 时间:2024/06/05 07:59

一 SDWebImage下载图片的基本操作

1 下载图片并显示(内存缓存&磁盘缓存)

 /*     第一个参数:图片的url地址     第二个参数:设置的占位图片     */    [self.imageView sd_setImageWithURL:[NSURL URLWithString:@"http://img3.a0bi.com/upload/ttq/20150125/1422148697268_middle.jpg"] placeholderImage:[UIImage imageNamed:@"Snip20160112_4"]];

2 下载图片显示并计算下载进度

2.1 代码实现内存缓存,磁盘缓存和下载进度
//下载图片&设置显示图片&内存缓存&磁盘缓存- (void)download{    //参数一:下载图片的路径    //参数二:占位图片    //参数三:下载选项    //参数四:进度回调    //参数五:完成回调    [self.imageView sd_setImageWithURL:[NSURL URLWithString:@"http://i.ce.cn/fashion/news/201603/04/W020160304475595612586.jpg"] placeholderImage:[UIImage imageNamed:@"/Users/xiaofeng/Desktop/Snip20160316_1.png"] options:SDWebImageLowPriority | SDWebImageCacheMemoryOnly progress:^(NSInteger receivedSize, NSInteger expectedSize) {        NSLog(@"%f",(float)receivedSize / expectedSize);    } completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, NSURL *imageURL) {        NSLog(@"%@---%@",error,[NSSearchPathForDirectoriesInDomains(NSApplicationDirectory, NSUserDomainMask, YES) lastObject]);        //判断缓存方式        switch (cacheType) {            case SDImageCacheTypeNone:                NSLog(@"直接下载的图片-----");                break;            case SDImageCacheTypeDisk:                NSLog(@"磁盘缓存图片-----");                break;            case SDImageCacheTypeMemory:                NSLog(@"内存缓存图片-----");                break;            default:                break;        }    }];}

3 下载图片不显示并且监听下载进度(用框架中的管理者模块)

3.1 代码实现内存缓存,磁盘缓存和下载进度
//下载图片&内存缓存&磁盘缓存- (void)download2{    [[SDWebImageManager sharedManager] downloadImageWithURL:[NSURL URLWithString:@"http://img3.a0bi.com/upload/ttq/20150125/1422148697268_middle.jpg"] options:kNilOptions progress:^(NSInteger receivedSize, NSInteger expectedSize) {        NSLog(@"%f",(float)receivedSize / expectedSize);    } completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, BOOL finished, NSURL *imageURL) {        NSLog(@"%@-----%@",error,[NSSearchPathForDirectoriesInDomains(NSApplicationDirectory, NSUserDomainMask, YES) lastObject]);        if (error == nil) {            self.imageView.image = image;        }    }];}

4 下载图片不显示并且不做任何的处理

4.1 注意:完成后回调是在子线程中处理的,刷新UI显示图片是在主线程中进行的
- (void)download3{    [[SDWebImageDownloader sharedDownloader] downloadImageWithURL:[NSURL URLWithString:@"http://image.zjg.js.cn/upload/editor/2014-7-1/2014711345189400th1b.jpg"] options:SDWebImageDownloaderLowPriority progress:^(NSInteger receivedSize, NSInteger expectedSize) {        NSLog(@"%f",(float)receivedSize / expectedSize);        NSLog(@"1-------%@",[NSThread currentThread]);    } completed:^(UIImage *image, NSData *data, NSError *error, BOOL finished) {        NSLog(@"2-------%@",[NSThread currentThread]);        //下载图片completed是在子线程中处理的,那么需要到主线程中刷新UI        dispatch_async(dispatch_get_main_queue(), ^{            NSLog(@"3--------%@",[NSThread currentThread]);            self.imageView.image = image;        });    }];}

5 播放Gif图片

//下载动态图- (void)download5{    NSURL *url = [NSURL URLWithString:@"http://img4q.duitang.com/uploads/item/201501/26/20150126180214_mAmSH.thumb.224_0.gif"];    NSData *data = [NSData dataWithContentsOfURL:url];    self.imageView.image = [UIImage sd_animatedGIFWithData:data];}

6 接收到内存发出来的警告,如何处理?

6.1 取消当前正在进行的所有的下载操作
[[SDWebImageManager sharedManager] cancelAll];
6.2 清除缓存数据
[[SDWebImageManager sharedManager].imageCache cleanDisk];[[SDWebImageManager sharedManager].imageCache clearMemory];
6.2.1 两者清除区别:
1> cleanDisk:删除过期的文件数据,计算当前未过期的已经下载的文件数据的大小,如果发现该数据大小大于我们设置的最大缓存数据大小,那么程序内部会按照按文件数据缓存的时间从远到近删除,知道小于最大缓存数据为止。2> clearMemory:直接删除文件,重新创建新的文件夹

7 SDWebImage框架内部的具体实现细节

7.1 判断当前图片类型:只判断图片二进制数据的第一个字节
7.2 默认的缓存周期:1周
7.3 缓存策略:默认情况下既做内存缓存又做磁盘缓存,下载图片前先检查内存缓存,再检查磁盘缓存
7.4 缓存的实现方式:采用了苹果推出的专门用来处理缓存的类NSCache
7.5 框架内部允许的最大并发数:6
7.6 对系统内存警告的处理方式:框架内部监听系统内存警告的通知,当发生后移除内存缓存中的所有对象
7.7 下载队列中对多个图片任务的处理方式:提供了FIFO和LIFO两种方式,默认为FIFO
7.8 如何下载图片:采用NSURLConnection发送网络请求,在其代理方法中接收数据并处理进度回调等工作
7.9 请求超时的设定:15秒
7.10 磁盘缓存图片的命名:以该图片的URL进行MD5散列加密【echo -n “url” |MD5】
7.11 缓存路径:~/Library/Caches/default/com.hackemist.SDWebImageCache.default
7.12 key—–>URL(如何优化):用黑名单(当一个URL请求失败后,会被添加到黑名单,可以有效的防止一个错误的URL被多次尝试下载)

二 RunLoop基本使用

1 RunLoop字面意思:跑圈

2 RunLoop实际含义:一个APP能一直运行的关键

3 注意:

(1)如果没有RunLoop,那么程序一启动就会退出,什么事情都做不了。
(2)如果有了RunLoop,那么相当于在内部有一个死循环,能够保证程序的持续运行
(3)main函数中的RunLoop
——a 在UIApplication函数内部就启动了一个RunLoop,该函数返回一个int类型的值
——b 这个默认启动的RunLoop是跟主线程相关联的

4 RunLoop与线程的关系

(1)RunLoop和线程的关系:一个RunLoop对应着一条唯一的线程
——问题:如何让子线程不死
——回答:给这条子线程开启一个RunLoop
(2)RunLoop的创建:主线程RunLoop已经创建好了,子线程的RunLoop需要手动创建
(3)RunLoop的生命周期:在第一次获取时创建,在线程结束时销毁

三 获取RunLoop对象

1 第一种类型的RunLoop:

1.1 获得当前线程对应的RunLoop
NSRunLoop *run = [NSRunLoop currentRunLoop];
1.2 获取主线程的RunLoop
NSRunLoop *run1 = [NSRunLoop mainRunLoop];

2 第二种类型的RunLoop

2.1 当前的RunLoop
CFRunLoopRef current = CFRunLoopGetCurrent();
2.2 获取主线程对应的RunLoop
CFRunLoopRef main = CFRunLoopGetMain();

3 注意点:

3.1 注意点:开一个子线程创建runloop,不是通过alloc init方法创建,而是直接通过调用currentRunLoop方法来创建,它本身是一个懒加载的。

3.2 在子线程中,如果不主动获取Runloop的话,那么子线程内部是不会创建Runloop的。可以下载CFRunloopRef的源码,搜索_CFRunloopGet0,查看代码。

3.3 Runloop对象是利用字典来进行存储,而且key是对应的线程Value为该线程对应的Runloop。

四 理解三张关于RunLoop的运行图

第一张图:RunLoop的处理逻辑

这里写图片描述
这里写图片描述

以上的描述是对第一张图的RunLoop运行描述

第二张图:通俗易懂图

这里写图片描述

特别说明:两张图其实描述的都差不多,只有第七点做了判断.

第三张图:mode(模式图)

这里写图片描述

解析第三张图:

注意: Runloop要想跑起来,它的内部必须要有一个mode,这个mode里面必须有source\observer\timer,至少要有其中的一个。
01. CFRunloopModeRef代表着Runloop的运行模式
02. 一个Runloop中可以有多个mode,一个mode里面又可以有多个source\observer\timer等等
03. 每次runloop启动的时候,只能指定一个mode,这个mode被称为该Runloop的当前mode
04. 如果需要切换mode,只能先退出当前Runloop,再重新指定一个mode进入
05. 这样做主要是为了分割不同组的定时器等,让他们相互之间不受影响
06. 系统默认注册了5个mode
—–a. kCFRunLoopDefaultMode:App的默认Mode,通常主线程是在这个Mode下运行
—–b. UITrackingRunLoopMode:界面跟踪 Mode,用于 ScrollView 追踪触摸滑动,保证界面滑动时不受其他 Mode 影响
—–c. UIInitializationRunLoopMode: 在刚启动 App 时第进入的第一个 Mode,启动完成后就不再使用
—–d. GSEventReceiveRunLoopMode: 接受系统事件的内部 Mode,通常用不到
—–e. kCFRunLoopCommonModes: 这是一个占位用的Mode,不是一种真正的Mode

五 总结

注意: 以上就是对SDWebImage框架和RunLoop的基本使用,还有很多不足的地方,我会找时间补上,大家有什么问题,可以给我留言,谢谢!!!!

1 0
原创粉丝点击