iOS网络加载图片缓存策略之ASIDownloadCache缓存优化
 

在我们实际工程中,很多情况需要从网络上加载图片,然后将图片在imageview中显示出来,但每次都要从网络上请求,会严重影响用户体验,为了不是每次显示都需要从网上下载数据,希望将图片放到本地缓存,因此我们需要一个好的的缓存策略,今天我将我在项目工程中的实际经验分享给大家,我这里主要介绍一下强大的ASIHTTPRequest的缓存策略,以及使用方法。

AD:

在我们实际工程中,很多情况需要从网络上加载图片,然后将图片在imageview中显示出来,但每次都要从网络上请求,会严重影响用户体验,为了不是每次显示都需要从网上下载数据,希望将图片放到本地缓存,因此我们需要一个好的的缓存策略,今天我将我在项目工程中的实际经验分享给大家,我这里主要介绍一下强大的ASIHTTPRequest的缓存策略,以及使用方法:

下面是具体步骤:

一、设置缓存策略

首先在SplitDemoAppDelegate委托代理中,实现如下代码:

在SplitDemoAppDelegate.h文件中,代码如下:

  1. #import <UIKit/UIKit.h>
  2. @class ASIDownloadCache;
  3. @interface SplitDemoAppDelegate : NSObject <UIApplicationDelegate,UITabBarControllerDelegate> {
  4. UIWindow *_window;
  5. ASIDownloadCache*_downloadCache;            //下载缓存策略
  6. }
  7. @property (nonatomic, retain) ASIDownloadCache*downloadCache;
  8. @end

在SplitDemoAppDelegate.m文件中,代码如下:

  1. #import "SplitDemoAppDelegate.h"
  2. @implementation SplitDemoAppDelegate
  3. @synthesize window=_window;
  4. @synthesize downloadCache = _downloadCache;
  5. - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary*)launchOptions
  6. {
  7. //初始化ASIDownloadCache缓存对象
  8. ASIDownloadCache *cache = [[ASIDownloadCache alloc] init];
  9. self.downloadCache = cache;
  10. [cache release];
  11. //路径
  12. NSArray *paths =NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask, YES);
  13. NSString *documentDirectory = [paths objectAtIndex:0];
  14. //设置缓存存放路径
  15. [self.downloadCache setStoragePath:[documentDirectorystringByAppendingPathComponent:@"resource"]];
  16. //设置缓存策略
  17. [self.downloadCache setDefaultCachePolicy:ASIOnlyLoadIfNotCachedCachePolicy];
  18. // Override point for customization after application launch.
  19. [self.window makeKeyAndVisible];
  20. return YES;
  21. }
  22. - (void)dealloc
  23. {
  24. [_window release];
  25. [_downloadCache release];
  26. [super dealloc];
  27. }
  28. @end

二、创建缓存线程

这一步是创建一个NSOperation类,实现缓存的方法,代码如下:

ResourceContainer.h文件实现:

  1. #import <Foundation/Foundation.h>
  2. #import "ASIHTTPRequest.h"
  3. #import "SplitDemoAppDelegate.h"
  4. @interface ResourceContainer : NSOperation {
  5. NSURL*_resourceURL;            //资源请求url
  6. NSObject*_hostObject;
  7. SEL_resourceDidReceive;      //资源接手响应方法
  8. SplitDemoAppDelegate*_appDelegate;            //应用委托对象
  9. ASIHTTPRequest*_httpRequest;
  10. UIImageView*_imageView;
  11. }
  12. @property (nonatomic, retain) NSURL*resourceURL;
  13. @property (nonatomic, retain) NSObject*hostObject;
  14. @property (nonatomic, assign) SELresourceDidReceive;
  15. @property (nonatomic, assign) SplitDemoAppDelegate   *appDelegate;
  16. @property (nonatomic, retain) ASIHTTPRequest*httpRequest;
  17. @property (nonatomic, retain) UIImageView*imageView;
  18. //http请求回调方法
  19. -(void)didStartHttpRequest:(ASIHTTPRequest *)request;
  20. -(void)didFinishHttpRequest:(ASIHTTPRequest *)request;
  21. -(void)didFailedHttpRequest:(ASIHTTPRequest *)request;
  22. //取消资源请求
  23. -(void)cancelReourceGet;
  24. //资源接收回调方法
  25. -(void)resourceDidReceive:(NSData *)resource;
  26. @end

ResourceContainer.m文件实现:

  1. #import "ResourceContainer.h"
  2. #import "HttpConstant.h"
  3. #import "ASIDownloadCache.h"
  4. @implementation ResourceContainer
  5. @synthesize resourceURL = _resourceURL;
  6. @synthesize hostObject = _hostObject;
  7. @synthesize resourceDidReceive = _resourceDidReceive;
  8. @synthesize appDelegate = _appDelegate;
  9. @synthesize httpRequest = _httpRequest;
  10. @synthesize imageView = _imageView;
  11. -(id)init{
  12. if(self == [super init]){
  13. self.appDelegate = (SplitDemoAppDelegate *)[[UIApplication        sharedApplication] delegate];
  14. }
  15. return self;
  16. }
  17. -(void)main{
  18. if(self.hostObject == nil)
  19. return;
  20. if(self.resourceURL == nil){
  21. [self resourceDidReceive:nil];
  22. return;
  23. }
  24. ASIHTTPRequest *request = [ASIHTTPRequest     requestWithURL:self.resourceURL]
  25. self.httpRequest = request;
  26. [self.httpRequest setDownloadCache:self.appDelegate.downloadCache];
  27. [self.httpRequest setDelegate:self];
  28. [self.httpRequest setDidStartSelector:@selector(didStartHttpRequest:)];
  29. [self.httpRequest setDidFinishSelector:@selector(didFinishHttpRequest:)];
  30. [self.httpRequest setDidFailSelector:@selector(didFailedHttpRequest:)];
  31. //发异步请求
  32. [self.httpRequest startAsynchronous];
  33. }
  34. - (void)dealloc {
  35. [_resourceURL release];
  36. [_hostObject release];
  37. [_httpRequest release];
  38. [_imageView release];
  39. [super dealloc];
  40. }
  41. //开始请求
  42. -(void)didStartHttpRequest:(ASIHTTPRequest *)request{
  43. [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:YES];
  44. }
  45. //请求成功返回处理结果
  46. -(void)didFinishHttpRequest:(ASIHTTPRequest *)request{
  47. [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO];
  48. if([request responseStatusCode] == 200 || [request responseStatusCode] == 304){
  49. //判断是否来自缓存
  50. if([request didUseCachedResponse]){
  51. NSLog(@"=========资源请求:%@ 来自缓存============",[self.resourceURL absoluteURL]);
  52. }
  53. else{
  54. NSLog(@"=========资源请求:图片不来自缓存============");
  55. }
  56. [self resourceDidReceive:[request responseData]];
  57. }
  58. else {
  59. [self resourceDidReceive:nil];
  60. }
  61. }
  62. //失败请求返回处理结果
  63. -(void)didFailedHttpRequest:(ASIHTTPRequest *)request{
  64. [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO];
  65. [self resourceDidReceive:nil];
  66. }
  67. //取消资源请求
  68. -(void)cancelReourceGet{
  69. [self.httpRequest cancel];
  70. }
  71. //资源接收处理方法
  72. -(void)resourceDidReceive:(NSData *)resource{
  73. if([self.hostObject respondsToSelector:self.resourceDidReceive]){
  74. if(resource != nil && self.imageView != nil){
  75. self.imageView.image = [UIImage imageWithData:resource];
  76. }
  77. [self.hostObject performSelectorOnMainThread:self.resourceDidReceive withObject:self.imageViewwaitUntilDone:NO];
  78. }
  79. }
  80. @end

到第二步,我们的缓存策略的设置,以及资源请求和接收数据方法已经构建完毕,下面介绍一下如何使用我们上面创建的NSOperation类

三、图片请求(利用上面创建的类)

这里以我的工程为例进行分析:

在DetailViewController.h声明文件中:

  1. #import <UIKit/UIKit.h>
  2. @interface DetailViewController :UIViewController {
  3. NSURL                         *_imageURL;                    //图片url
  4. NSMutableArray            *_originalIndexArray;        //保存请求图片的号
  5. NSMutableDictionary     *_originalOperationDic;     //保存图片请求队列
  6. NSOperationQueue        *_requestImageQueue;    //图片请求队列
  7. }
  8. @property (nonatomic, retain) NSURL                       *imageURL;
  9. @property (nonatomic, retain) NSMutableArray          *originalIndexArray;
  10. @property (nonatomic, retain) NSMutableDictionary   *originalOperationDic;
  11. @property (nonatomic, retain) NSOperationQueue      * requestImageQueue;
  12. //显示图片信息
  13. -(void)displayProductImage;
  14. //根据图片序号显示请求图片资源
  15. -(void)displayImageByIndex:(NSInteger)index ByImageURL:(NSURL *)url;
  16. //处理图片请求返回信息
  17. -(void)imageDidReceive:(UIImageView *)imageView;
  18. @end

在DetailViewController.m实现文件中:

  1. #import "ProductDetailViewController.h"
  2. //这里引入在第二步中,我们创建的对象
  3. #import "ResourceContainer.h"
  4. @implementation DetailViewController
  5. @synthesize imageURL = _imageURL;
  6. @synthesize originalIndexArray = _originalIndexArray;
  7. @synthesize originalOperationDic = _originalOperationDic;
  8. @synthesize requestImageQueue = _requestImageQueue;
  9. - (void)viewDidLoad
  10. {
  11. [super viewDidLoad];
  12. NSOperationQueue *tempQueue = [[NSOperationQueue alloc] init];
  13. self.requsetImageQueue = tempQueue;
  14. [tempQueue release];
  15. NSMutableArray *array = [[NSMutableArray alloc] init];
  16. self.originalIndexArray = array;
  17. [array release];
  18. NSMutableDictionary *dic = [[NSMutableDictionary alloc] init];
  19. self.originalOperationDic = dic;
  20. [dic release];
  21. }
  22. //显示图片信息
  23. -(void)displayProductImage
  24. {
  25. NSURL *url = [NSURL URLWithString:@"http://xxx.xxx.xxx.xxx"];
  26. //这个是从器返回有图片数目,self.xxxx根据具体的场合
  27. int imageCount = [self.xxxx.imageNum intValue];
  28. for (int i=0; i<imageCount; i++) {
  29. NSString *str1 = @"这里是拼图片请求url,根据实际需求";
  30. self.imageURL = [url URLByAppendingPathComponent:str1];
  31. //根据图片号请求资源
  32. [self displayImageByIndex:i ByImageURL:self.productImageURL];
  33. }
  34. }
  35. //根据图片序号显示请求图片资源
  36. -(void) displayImageByIndex:(NSInteger)index ByImageURL:(NSURL *)url
  37. {
  38. NSString *indexForString = [NSString stringWithFormat:@"%d",index];
  39. //若数组中已经存在该图片编号,说明图片加载完毕,直接返回
  40. if ([self.originalIndexArray containsObject:indexForString]) {
  41. return;
  42. }
  43. //创建UIImageView对象
  44. UIImageView *imageView = [[UIImageView alloc] init];
  45. imageView.tag = index;
  46. //创建资源请求对象
  47. ResourceContainer  *imageOperation = [[ResourceContainer alloc] init];
  48. imageOperation.resourceURL = url;
  49. imageOperation.hostObject = self;
  50. //设置收到图片信息处理理方法
  51. imageOperation.resourceDidReceive = @selector(imageDidReceive:);
  52. imageOperation.imageView = imageView;
  53. [imageView release];
  54. //将图片请求对象加入图片请求队列中
  55. [self.requsetImageQueue addOperation:imageOperation];
  56. [self.originalOperationDic setObject:imageOperation forKey:indexForString];
  57. [imageOperation release];
  58. }
  59. //处理图片请求返回信息
  60. -(void)imageDidReceive:(UIImageView *)imageView
  61. {
  62. if (imageView == nil||imageView.image == nil) {
  63. imageView.image = [UIImage imageNamed:@"no-pic-300-250.png"];
  64. }
  65. //将图片信息加载到前台,self.openFlowView是我用的coverFlow,coverFlow的使用方法网上很多,自己找吧
  66. [self.openFlowView setImage:imageView.image forIndex:imageView.tag];
  67. [self.originalIndexArray addObject:[NSString stringWithFormat:@"%d",imageView.tag]];
  68. [self.originalOperationDic removeObjectForKey:[NSString stringWithFormat:@"%d",imageView.tag]];
  69. }
  70. - (void)dealloc
  71. {
  72. [_requestImageQueue release];
  73. [_originalIndexArray release];
  74. [_originalOperationDic release];
  75. [_imageURL release];
  76. [super dealloc];
  77. }
  78. @end

经过上述步骤,我们实现了加载网络图片时缓存功能,增强了用户体验效果。代码中可能会有诸多问题,希望网友指教,有更好的缓存方法,也希望一起交流!

经验总结。本书共17章,

 
 

iOS网络加载图片缓存策略之ASIDownloadCache缓存优化的更多相关文章

  1. iOS网络加载图片缓存与SDWebImage

    加载网络图片可以说是网络应用中必备的.如果单纯的去下载图片,而不去做多线程.缓存等技术去优化,加载图片时的效果与用户体验就会很差. 一.自己实现加载图片的方法 tips: *iOS中所有网络访问都是异 ...

  2. android 网络加载图片,对图片资源进行优化,并且实现内存双缓存 + 磁盘缓存

    经常会用到 网络文件 比如查看大图片数据 资源优化的问题,当然用开源的项目  Android-Universal-Image-Loader  或者 ignition 都是个很好的选择. 在这里把原来 ...

  3. Android加载图片的策略

    实现图片缓存也不难,需要有相应的cache策略.这里我采用 内存-文件-网络 三层cache机制,其中内存缓存包括强引用缓存和软引用缓存(SoftReference),其实网络不算cache,这里姑且 ...

  4. 【转】Android循环滚动广告条的完美实现,封装方便,平滑过渡,从网络加载图片,点击广告进入对应网址

    Android循环滚动广告条的完美实现,封装方便,平滑过渡,从网络加载图片,点击广告进入对应网址 关注finddreams,一起分享,一起进步: http://blog.csdn.net/finddr ...

  5. swift 基础小结01 --delegate、Optional、GCD的使用、request请求、网络加载图片并保存到沙箱、闭包以及桥接

    本文主要记录swift中delegate的使用.“?!”Optional的概念.GCD的使用.request请求.网络加载图片并保存到沙箱.闭包以及桥接. 一.delegate的使用 swift中de ...

  6. ios -网络加载json和本地加载json

    1网络加载json的时候,要在模型的实现文件里写: - (void)setValue:(id)value forKey:(NSString *)key { } 2本地加载json的时候,要在模型的实现 ...

  7. LruCache:从网络加载图片缓存实例

    OOM异常 堆内存用于存储实例对象,当程序不断创建对象,并且对象都有引用指向,那么垃圾回收机制就不会清理这些对象,当对象多到挤满堆内存的上限后,就产生OOM异常.Android系统为每个应用程序使用的 ...

  8. 关于ios异步加载图片的几个开源项目

    一.HjCache  原文:http://www.markj.net/hjcache-iphone-image-cache/ 获取 HJCache: HJCache is up on github h ...

  9. 使用自定义的item、Adapter和AsyncTask、第三方开源框架PullToRefresh联合使用实现自定义的下拉列表(从网络加载图片显示在item中的ImageView)

    AsyncTask使用方法详情:http://www.cnblogs.com/zzw1994/p/4959949.html 下拉开源框架PullToRefresh使用方法和下载详情:http://ww ...

随机推荐

  1. D2 前端技术论坛总结(下)

    此篇文章不接上篇了,下午4场我就不一一介绍了,主要总结下 D2 整场下来都讲了些什么.   整场下来,就3个关键词:nodejs,多终端,工程化   nodejs 从杭js到d2,大会上提到最多的词汇 ...

  2. jquery 和 $

    而jQuery就是jQuery库提供的一个函数.(好像也不仅仅只是函数, 因为还有 $.ajax(options) 这样的使用,等同 jQuery.ajax(options)) 这个函数的作用是根据 ...

  3. SqlServer 之 查看表空间

    一.用到系统视图 sys.sysindexes 该视图定义如下: CREATE VIEW sys.sysindexes AS SELECT id, status = convert(int, end ...

  4. SQL Server 表和索引存储结构

    在上一篇文章中,我们介绍了SQL Server数据文件的页面类型,系统通过96个字节的头部信息和系统表从逻辑层面上将表的存储结构管理起来,具体到表的存储结构上,SQL Server引入对象.分区.堆或 ...

  5. 【阿里云产品评测】小站长眼中的巅峰云PK

    [阿里云产品评测]小站长眼中的巅峰云PK 阿里云论坛用户:昵称-a5lianmeng 笔者是一名小站长,因狂热互联网,而在毕业后由宅男逐渐进入站长队伍,在毕业后的几年间,经营6个流量类网站,身为站长, ...

  6. C#实现插件式架构的方法

    插件式架构,一种全新的.开放性的.高扩展性的架构体系.插件式架构设计近年来非常流行,基于插件的设计好处很多,把扩展功能从框架中剥离出来,降低了框架的复杂度,让框架更容易实现.扩展功能与框架以一种很松的 ...

  7. 解决xcode7添加启动图片不显示

    xcode7添加启动图片步骤: 在target中将Launch Screen File置为空,不使用自带的LaunchScreen.storyboard作为启动图(LaunchScreen.story ...

  8. Java中Integer的最大值和最小值

    从JDK1.0开始,Integer中就定义了MIN_VALUE和MAX-VALUE两个常量: /** * A constant holding the minimum value an {@code ...

  9. [freemarker篇]04.简单介绍-基本数据类型

    好几天没有更新博客了,最近一顿乱七八糟的忙!今天简单更新第四章,这里只能说是简单介绍,因为权威的还是需要看Freemarker的官方中文手册! 好几天没有更新博客了,最近一顿乱七八糟的忙!今天简单更新 ...

  10. 在IIS上发布项目后浏览时报的错:Unable to make the session state request to the session state server

    错误描述: Unable to make the session state request to the session state server. Please ensure that the A ...