前段时间写界面,因为数据的请求分成了两部分,所以用到了多线程,实现数据的分步请求,然后自己写了一个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缓存机制的验证的更多相关文章

  1. 在ASP.Net中两种利用CSS实现多界面的方法

    通过使页面动态加载不同CSS实现多界面(类型于csdn的blog): 方法一: <%@page language="C#"%><%@import namespac ...

  2. QT中获取选中的radioButton的两种方法(动态取得控件的objectName之后,对名字进行比较)

    QT中获取选中的radioButton的两种方法   QT中要获取radioButton组中被选中的那个按钮,可以采用两种如下两种办法进行: 方法一:采用对象名称进行获取 代码: 1 QRadioBu ...

  3. Java 爬虫遇上数据异步加载,试试这两种办法!

    这是 Java 爬虫系列博文的第三篇,在上一篇 Java 爬虫遇到需要登录的网站,该怎么办? 中,我们简单的讲解了爬虫时遇到登录问题的解决办法,在这篇文章中我们一起来聊一聊爬虫时遇到数据异步加载的问题 ...

  4. Android中BroadcastReceiver的两种注册方式(静态和动态)详解

    今天我们一起来探讨下安卓中BroadcastReceiver组件以及详细分析下它的两种注册方式. BroadcastReceiver也就是"广播接收者"的意思,顾名思义,它就是用来 ...

  5. lucene的两种分页操作

    基于lucene的分页有两种: lucene3.5之前分页提供的方式为再查询方式(每次查询全部记录,然后取其中部分记录,这种方式用的最多),lucene官方的解释:由于我们的速度足够快.处理海量数据时 ...

  6. JFreeChart与AJAX+JSON+ECharts两种处理方式生成热词统计可视化图表

    本篇的思想:对HDFS获取的数据进行两种不同的可视化图表处理方式.第一种JFreeChar可视化处理生成图片文件查看.第二种AJAX+JSON+ECharts实现可视化图表,并呈现于浏览器上.   对 ...

  7. SAPUI5 freestyle vs SAP Fiori Elements —— 两种开发SAP UI5 Apps的方式对比

    概述 目前SAPUI5 SDK 提供了两种方式来开发一个SAPUI5 App.一种方式是传统的SAPUI5开发方式,一种是利用SAP Fiori Elements通过模板快速构建应用的方式. 本文简单 ...

  8. 使用Python生成源文件的两种方法

    利用Python的字符串处理模块,开发者能够编写脚本用来生成那些格式同样的C.C++.JAVA源程序.头文件和測试文件,从而避免大量的反复工作. 本文概述两种利用Python string类生成jav ...

  9. FTP两种工作模式:主动模式(Active FTP)和被动模式

    在主动模式下,FTP客户端随机开启一个大于1024的端口N向服务器的21号端口发起连接,然后开放N+1号端口进行监听,并向服务器发出PORT N+1命令.服务器接收到命令后,会用其本地的FTP数据端口 ...

随机推荐

  1. [LeetCode] Self Dividing Numbers 自整除数字

    A self-dividing number is a number that is divisible by every digit it contains. For example, 128 is ...

  2. [LeetCode] Longest Uncommon Subsequence I 最长非共同子序列之一

    Given a group of two strings, you need to find the longest uncommon subsequence of this group of two ...

  3. 用AJAX实现上传图片或者文件的方法

    大家好,我是小C,最近在项目中用到ajax上传图片文件,本篇我们就说说ajax上传文件. 我们平时用到的AJAX,大部分都是传几个参数就可以了.简单说就是传几个字符串. $.ajax({ url: u ...

  4. [HNOI 2014]道路堵塞

    Description A国有N座城市,依次标为1到N.同时,在这N座城市间有M条单向道路,每条道路的长度是一个正整数.现在,A国 交通部指定了一条从城市1到城市N的路径,并且保证这条路径的长度是所有 ...

  5. 成也DP,败也DP(AFO?)

    不知道想说什么.. 从来没写过博客,markdown什么的也不会,凑合着看一下吧. 初中的时候开始搞OI,学了两个月后普及组爆零就退赛了. 初三直升的时候说每个人都要选竞赛,抱着混一混的心态选了信息, ...

  6. 例10-5 uva12716

    题意:gcd(a,b) = a^b,( 1≤ a , b ≤ n) 思路: ① a^b = c, 所以 a^c = b,而且c是a的约数,枚举a,c,再gcd判断 ② 打表可知 a-b = c,而且a ...

  7. bzoj省选十连测推广赛

    A.普通计算姬 题意:给丁一棵树,每个点有一个权值,用sum(x)表示以x为根的子树的权值和,要求支持两种操作: 1 u v  :修改点u的权值为v. 2 l  r   :  求∑sum[i] l&l ...

  8. CentOS7快速配置nginx node mysql8.0

    目录: (一)基础准备 (二)安装node (三)安装nginx (四)安装mySql8.0 (五)整体配置 (六)安装PM2守护进程 (一)基础准备1.1 概述 服务器操作系统为 centos7.4 ...

  9. python3全栈开发-并发编程的多进程理论

    一. 什么是进程 进程:正在进行的一个过程或者说一个任务.而负责执行任务则是cpu. 举例(单核+多道,实现多个进程的并发执行): duoduo在一个时间段内有很多任务要做:python备课的任务,写 ...

  10. postman 模拟请求中添加 header,post请求中传json参数

    1. GET 请求 2.Post 请求 (请求参数为Json,header中带有参数) 问题延伸 GET请求不能够 添加 Body 吗?[答案]