两种利用GCD实现分步获取结果的方式和SDWebImage缓存机制的验证
前段时间写界面,因为数据的请求分成了两部分,所以用到了多线程,实现数据的分步请求,然后自己写了一个Demo,用两种方式实现分步获取内容,其中也包含了验证SDWebImage这个库的缓存机制,在这里给大家分享一下,希望对大家有用,不喜勿喷~~
首先想要说的是GCD线程分步实现的过程,代码如下:(相关文字说明在代码中都包含)
#pragma mark --------- 并行异步执行的方法:利用GCD并行多个线程并且等待所有线程结束之后再执行其它方法
- (void)pushRequstData1 {
__weak typeof (self) selfVc = self;
dispatch_group_t group = dispatch_group_create();
dispatch_group_async(group, dispatch_get_global_queue(0,0), ^{
// 并行执行的线程一
NSLog(@"11111111");
[selfVc oneOne];
NSLog(@".........11111111");
});
dispatch_group_async(group, dispatch_get_global_queue(0,0), ^{
// 并行执行的线程二
NSLog(@"44444444");
[selfVc twoTwo];
NSLog(@".........22222222");
});
dispatch_group_notify(group, dispatch_get_global_queue(0,0), ^{
// 汇总结果
NSLog(@"这里可以最后刷新数据,更新界面。。。。77777777");
});
}
#pragma mark --------- 串行异步执行的方法:利用GCD串行多个线程,必须等到上一个完成之后,才能执行下一个任务,并且可以等待所有线程结束之后再执行其它方法
- (void)pushRequstData2 {
__weak typeof (self) selfVc = self;
//利用GCD串行多个线程,按顺序完成各个任务,并且等待所有线程结束之后再执行其它任务
dispatch_group_t group = dispatch_group_create();
dispatch_queue_t queue1 = dispatch_queue_create("queue1", DISPATCH_QUEUE_SERIAL);
dispatch_group_async(group, queue1, ^{
// 串行执行的线程一
NSLog(@"11111111");
[selfVc oneOne];
});
dispatch_group_async(group, queue1, ^{
// 串行执行的线程二
NSLog(@"44444444");
[selfVc twoTwo];
});
dispatch_group_notify(group, queue1, ^{
// 汇总结果
NSLog(@"这里可以最后刷新数据,更新界面。。。。77777777");
});
}
//方法执行
/*注意:
1.注意循环引用的问题,如果有用到self,要使用弱引用:__weak typeof (self) selfVc = self;这样效果最好,防止循环引用的问题
*/
//[self pushRequstData1];//这个是并行异步的方法,oneOne和twoTwo方法会同时进行,所以执行的顺序不是1234567
[self pushRequstData2];//这个是串行异步执行的方法,会等线程一执行完成,才会执行线程二,所以执行的顺序是1234567
接下来就是验证SDWebImage缓存图片的代码,突发奇想写这个是因为,看到支付宝,爱奇艺等相关APP,在不连接网络的情况下还会显示图片,所以为了实现这一效果和验证缓存机制,写了这些代码,希望对大家有帮助,代码如下:
/**
验证步骤:
1:首先连接网络运行APP,并显示图片;
2:结束APP,退出程序,记得双击home键,把此APP进程删除;
3:关闭网络,运行APP,并进入显示图片的界面,发现在没有网络的情况下,之前通过网络请求的图片显示了,说明SDWebImage已经把图片下载进行了缓存。
**/
//添加图片
-(void)addImgV:(NSArray *)arr
{
if (arr.count<=0) {
_dataArray = [NSArray arrayWithContentsOfFile:[self saveLocalPath:@"dataStr1"]];
}else{
//存入本地,方便没网时,读取缓存在本地的图片文件
_dataArray = [NSArray arrayWithArray:arr];
[_dataArray writeToFile:[self saveLocalPath:@"dataStr1"] atomically:YES];
}
for (int i = 0; i < _dataArray.count; i++) {
NSDictionary *dic = _dataArray[i];
UIImageView *imgV = [[UIImageView alloc] initWithFrame:CGRectMake(0, 100+i*130, 200, 120)];
[imgV sd_setImageWithURL:[NSURL URLWithString:[NSString stringWithFormat:@"https://image.healthmanage.cn/qImage/%@",dic[@"imagePath"]]] placeholderImage:[UIImage imageNamed:@"guanggao.png"]];
[self.view addSubview:imgV];
}
}
//缓存到本地的数据方法,强烈建议创建的文件名称使用宏定义方式,以防拼写或读取数据时出错
-(NSString *)saveLocalPath:(NSString *)strPath
{
NSArray *arr = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentPathStr = arr[0];
NSString *dataPathStr = [documentPathStr stringByAppendingPathComponent:[NSString stringWithFormat:@"%@.plist",strPath]];
return dataPathStr;
}
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 可以预先下载图片,方便后续使用。
相关代码,请自行研究,很简单(源码:https://github.com/hbblzjy/OCGCDMoreDispath)
两种利用GCD实现分步获取结果的方式和SDWebImage缓存机制的验证的更多相关文章
- 在ASP.Net中两种利用CSS实现多界面的方法
通过使页面动态加载不同CSS实现多界面(类型于csdn的blog): 方法一: <%@page language="C#"%><%@import namespac ...
- QT中获取选中的radioButton的两种方法(动态取得控件的objectName之后,对名字进行比较)
QT中获取选中的radioButton的两种方法 QT中要获取radioButton组中被选中的那个按钮,可以采用两种如下两种办法进行: 方法一:采用对象名称进行获取 代码: 1 QRadioBu ...
- Java 爬虫遇上数据异步加载,试试这两种办法!
这是 Java 爬虫系列博文的第三篇,在上一篇 Java 爬虫遇到需要登录的网站,该怎么办? 中,我们简单的讲解了爬虫时遇到登录问题的解决办法,在这篇文章中我们一起来聊一聊爬虫时遇到数据异步加载的问题 ...
- Android中BroadcastReceiver的两种注册方式(静态和动态)详解
今天我们一起来探讨下安卓中BroadcastReceiver组件以及详细分析下它的两种注册方式. BroadcastReceiver也就是"广播接收者"的意思,顾名思义,它就是用来 ...
- lucene的两种分页操作
基于lucene的分页有两种: lucene3.5之前分页提供的方式为再查询方式(每次查询全部记录,然后取其中部分记录,这种方式用的最多),lucene官方的解释:由于我们的速度足够快.处理海量数据时 ...
- JFreeChart与AJAX+JSON+ECharts两种处理方式生成热词统计可视化图表
本篇的思想:对HDFS获取的数据进行两种不同的可视化图表处理方式.第一种JFreeChar可视化处理生成图片文件查看.第二种AJAX+JSON+ECharts实现可视化图表,并呈现于浏览器上. 对 ...
- SAPUI5 freestyle vs SAP Fiori Elements —— 两种开发SAP UI5 Apps的方式对比
概述 目前SAPUI5 SDK 提供了两种方式来开发一个SAPUI5 App.一种方式是传统的SAPUI5开发方式,一种是利用SAP Fiori Elements通过模板快速构建应用的方式. 本文简单 ...
- 使用Python生成源文件的两种方法
利用Python的字符串处理模块,开发者能够编写脚本用来生成那些格式同样的C.C++.JAVA源程序.头文件和測试文件,从而避免大量的反复工作. 本文概述两种利用Python string类生成jav ...
- FTP两种工作模式:主动模式(Active FTP)和被动模式
在主动模式下,FTP客户端随机开启一个大于1024的端口N向服务器的21号端口发起连接,然后开放N+1号端口进行监听,并向服务器发出PORT N+1命令.服务器接收到命令后,会用其本地的FTP数据端口 ...
随机推荐
- 学习React系列(一)——React.Component 生命周期
挂载中(只执行一次) 以下方法在组件实例正被创建和插入到DOM中时调用 constructor()一般用于初始化state和方法的this绑定 componentWillMount() render( ...
- Spting +Spring MVC+spring date jsp +hibernate+jq
controller 控制页面跳转 处理前台后台数据交互 访问servicedao层:@Repository 数据库访问层 增删改查 jpa规范了hibernate jap仓库 jpa自动解析 方法名 ...
- [LeetCode] Longest Word in Dictionary 字典中的最长单词
Given a list of strings words representing an English Dictionary, find the longest word in words tha ...
- 使用Remix编译和部署以太坊智能合约
Remix 是一個开源的 Solidity 智能合约开发环境,提供基本的编译.部署至本地或测试网络.执行合约等功能.Solidity 是 以太坊Ethereum 官方设计和支持的开发语言,专门用于 ...
- CentOS6.9安装
我安装在VM的虚拟机中.具体安装方式网上很多,由于本机只能安装32位的linux系统,所以悬在了Centsos6.9版本.点此下载. 其中有一种是叫做LIVEDVD的版本,这种的值虚拟机中配置后,打开 ...
- SAC E#1 - 一道难题 Tree
题目背景 冴月麟和魏潇承是好朋友. 题目描述 冴月麟为了守护幻想乡,而制造了幻想乡的倒影,将真实的幻想乡封印了.任何人都无法进入真实的幻想乡了,但是她给前来救她的魏潇承留了一个线索. 她设置了一棵树( ...
- 绝世好题bzoj4300
Description 给定一个长度为n的数列ai,求ai的子序列bi的最长长度,满足bi&bi-1!=0(2<=i<=len). Input 输入文件共2行. 第一行包括一个整数 ...
- ●POJ 1556 The Doors(简单计算几何+最短路)
●赘述题目 10*10的房间内,有竖着的一些墙(不超过18个).问从点(0,5)到(10,5)的最短路. 按照输入样例,输入的连续5个数,x,y1,y2,y3,y4,表示(x,0--y1),(x,y2 ...
- NOIP2014-11-3模拟赛
字符串 题目描述 现在给一个字符串,你要做的就是当这个字符串中存在两个挨着的字符是相同的时就将这两个字符消除.需要注意的是,当把这两个字符消除后,可能又产生一对新的挨着的字符是相同的.比如,初始的字符 ...
- hdu 4897 树链剖分(重轻链)
Little Devil I Time Limit: 16000/8000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others ...