两种利用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数据端口 ...
随机推荐
- disabled OR readonly
1.对元素设置disabled以及readonly属性 $("#uid").attr("disabled",true); $("#uid") ...
- 一、spring的成长之路——代理设计模式
java常用的设计模式详解: 1.代理模式(JDK的动态代理) [IDept.java] 这是一个简单的就接口,进行数据的更新 package com.itcloud.pattern.proxy; ...
- [LeetCode] Candy Crush 糖果消消乐
This question is about implementing a basic elimination algorithm for Candy Crush. Given a 2D intege ...
- Jmeter启动问题总结
下载下来的jmeter文件,双击jmeter.bat文件打开的时候,系统提示如下: 查询安装的环境,java的jdk存在,并且版本在1.7以上,详情如下: 在环境变量PATH中添加:%SystemRo ...
- .NET CORE 2.0 踩坑记录之ConfigurationManager
在之前.net framework 中使用的ConfigurationManager还是很方便的,不过在.NET CORE 2.0中SDK默认已经不存在ConfigurationManager. 那么 ...
- codevs 2621 土地侵蚀
提交地址:http://codevs.cn/problem/2621/ 2621 土地侵蚀 时间限制: 1 s 空间限制: 32000 KB 题目等级 : 黄金 Gold 题目描述 De ...
- [ZJOI2008]泡泡堂
题目描述 第XXXX届NOI期间,为了加强各省选手之间的交流,组委会决定组织一场省际电子竞技大赛,每一个省的代表队由n名选手组成,比赛的项目是老少咸宜的网络游戏泡泡堂.每一场比赛前,对阵双方的教练向组 ...
- STL注意比较函数
可重复插入?: set<int ,less_equal<int> >s; s.insert(10); s.insert(10); 第二次调用insert,集合回去确认10是否已 ...
- 51nod 1035:最长的循环节
1035 最长的循环节 基准时间限制:1 秒 空间限制:131072 KB 分值: 20 难度:3级算法题 正整数k的倒数1/k,写为10进制的小数如果为无限循环小数,则存在一个循环节,求< ...
- Elasticsearch 创建、更新、删除文档、处理冲突
----创建新文档---- 1._index,_type和_id的组合可以唯一标识一个文档,所以确保一个新文档的最简单的办法就是,使用索引请求的POST形式让elsticsearch自动生成唯一_id ...