IOS开发网络加载图片缓存策略之──ASIDownloadCache缓存策略

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

 

    下面是具体步骤:

一、设置缓存策略

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

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

 

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

 

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

复制代码
 1 #import "SplitDemoAppDelegate.h"
 2 
 3 @implementation SplitDemoAppDelegate
 4 
 5 @synthesize window=_window;
 6 
 7 @synthesize downloadCache = _downloadCache;
 8 
 9 - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary*)launchOptions
10 
11 {
12 
13     //初始化ASIDownloadCache缓存对象 14 
15    ASIDownloadCache *cache = [[ASIDownloadCache alloc] init];
16 
17    self.downloadCache = cache;
18 
19   [cache release];
20 
21 
22    //路径 23 
24    NSArray *paths =NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask, YES);
25 
26   NSString *documentDirectory = [paths objectAtIndex:0];
27 
28    //设置缓存存放路径 29 
30    [self.downloadCache setStoragePath:[documentDirectorystringByAppendingPathComponent:@"resource"]];
31 
32    //设置缓存策略 33 
34     [self.downloadCache setDefaultCachePolicy:ASIOnlyLoadIfNotCachedCachePolicy];
35 
36     // Override point for customization after application launch. 37 
38     [self.window makeKeyAndVisible];
39 
40     return YES;
41 
42 }
43 
44 
45 - (void)dealloc
46 
47 {
48 
49     [_window release];
50 
51     [_downloadCache release];
52 
53    [super dealloc];
54 
55 }
56 
57 @end
复制代码

 

    二、创建缓存线程

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

    ResourceContainer.h文件实现:

 

复制代码
 1 #import <Foundation/Foundation.h>
 2 
 3 #import "ASIHTTPRequest.h"
 4 
 5 #import "SplitDemoAppDelegate.h"
 6 
 7  
 8 
 9 @interface ResourceContainer : NSOperation {
10 
11 NSURL*_resourceURL;            //资源请求url 12 
13 NSObject*_hostObject;             
14 
15 SEL_resourceDidReceive;      //资源接手响应方法  16 
17 SplitDemoAppDelegate*_appDelegate;            //应用委托对象 18 
19 ASIHTTPRequest*_httpRequest;            
20 
21 UIImageView*_imageView;              
22 
23 }
24 
25  
26 
27 @property (nonatomic, retain) NSURL*resourceURL;
28 
29 @property (nonatomic, retain) NSObject*hostObject;
30 
31 @property (nonatomic, assign) SELresourceDidReceive;
32 
33 @property (nonatomic, assign) SplitDemoAppDelegate   *appDelegate;
34 
35 @property (nonatomic, retain) ASIHTTPRequest*httpRequest;
36 
37 @property (nonatomic, retain) UIImageView*imageView;
38 
39  
40 
41 //http请求回调方法 42 
43 -(void)didStartHttpRequest:(ASIHTTPRequest *)request;
44 
45 -(void)didFinishHttpRequest:(ASIHTTPRequest *)request;
46 
47 -(void)didFailedHttpRequest:(ASIHTTPRequest *)request;
48 
49  
50 
51 //取消资源请求 52 
53 -(void)cancelReourceGet;
54 
55 //资源接收回调方法 56 
57 -(void)resourceDidReceive:(NSData *)resource;
58 
59 @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 
 12 -(id)init{
 13 
 14      if(self == [super init]){
 15 
 16      self.appDelegate = (SplitDemoAppDelegate *)[[UIApplication        sharedApplication] delegate];
 17 
 18       }
 19 
 20    return self;
 21 
 22 }
 23 
 24 
 25 -(void)main{
 26 
 27       if(self.hostObject == nil)
 28       return;
 29 
 30      if(self.resourceURL == nil){
 31           [self resourceDidReceive:nil];
 32           return;
 33      }
 34 
 35       ASIHTTPRequest *request = [ASIHTTPRequest     requestWithURL:self.resourceURL]
 36       self.httpRequest = request;
 37 
 38  
 39 
 40 [self.httpRequest setDownloadCache:self.appDelegate.downloadCache];
 41 [self.httpRequest setDelegate:self];
 42 [self.httpRequest setDidStartSelector:@selector(didStartHttpRequest:)];
 43 [self.httpRequest setDidFinishSelector:@selector(didFinishHttpRequest:)];
 44 [self.httpRequest setDidFailSelector:@selector(didFailedHttpRequest:)];
 45 
 46     //发异步请求
 47 
 48 [self.httpRequest startAsynchronous];
 49 
 50 }
 51 
 52 - (void)dealloc {
 53 
 54 [_resourceURL release];
 55 [_hostObject release];
 56 [_httpRequest release];
 57 [_imageView release];
 58 [super dealloc];
 59 
 60 }
 61 
 62 //开始请求
 63 
 64 -(void)didStartHttpRequest:(ASIHTTPRequest *)request{
 65 
 66 [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:YES];
 67 
 68 }
 69 
 70 //请求成功返回处理结果
 71 
 72 -(void)didFinishHttpRequest:(ASIHTTPRequest *)request{
 73 
 74 [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO];
 75 
 76  
 77 
 78     if([request responseStatusCode] == 200 || [request responseStatusCode] == 304){
 79 
 80 //判断是否来自缓存
 81 
 82         if([request didUseCachedResponse]){
 83 
 84 NSLog(@"=========资源请求:%@ 来自缓存============",[self.resourceURL absoluteURL]);
 85 
 86         }
 87          else{
 88 
 89             NSLog(@"=========资源请求:图片不来自缓存============");
 90         }
 91 
 92 
 93      [self resourceDidReceive:[request responseData]];
 94 
 95 }
 96 
 97 else {
 98 
 99        [self resourceDidReceive:nil];
100 
101        }
102 
103 }
104 
105 //失败请求返回处理结果
106 
107 -(void)didFailedHttpRequest:(ASIHTTPRequest *)request{
108 
109 [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO];
110 
111 [self resourceDidReceive:nil];
112 
113 }
114 
115 //取消资源请求
116 
117 -(void)cancelReourceGet{
118 
119 [self.httpRequest cancel];
120 
121 }
122 
123 //资源接收处理方法
124 
125 -(void)resourceDidReceive:(NSData *)resource{
126 
127 if([self.hostObject respondsToSelector:self.resourceDidReceive]){
128 
129 if(resource != nil && self.imageView != nil){
130 
131 self.imageView.image = [UIImage imageWithData:resource];
132 
133 }
134 
135 
136 [self.hostObject performSelectorOnMainThread:self.resourceDidReceive withObject:self.imageViewwaitUntilDone:NO];
137 
138 }
139 
140 }
141 
142 @end 
复制代码

 

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

 

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

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

在DetailViewController.h声明文件中:

 

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



 

 在DetailViewController.m实现文件中:

复制代码
  1 #import "ProductDetailViewController.h"
  2 
  3 //这里引入在第二步中,我们创建的对象
  4 #import "ResourceContainer.h"
  5 
  6 @implementation DetailViewController
  7 @synthesize imageURL = _imageURL;
  8 @synthesize originalIndexArray = _originalIndexArray;
  9 @synthesize originalOperationDic = _originalOperationDic;
 10 @synthesize requestImageQueue = _requestImageQueue;
 11 
 12 
 13 - (void)viewDidLoad
 14 
 15 {
 16 
 17      [super viewDidLoad];
 18      NSOperationQueue *tempQueue = [[NSOperationQueue alloc] init];
 19 
 20      self.requsetImageQueue = tempQueue;
 21      [tempQueue release];
 22 
 23       NSMutableArray *array = [[NSMutableArray alloc] init];
 24 
 25       self.originalIndexArray = array;
 26       [array release];
 27 
 28        NSMutableDictionary *dic = [[NSMutableDictionary alloc] init];
 29 
 30        self.originalOperationDic = dic;
 31        [dic release];
 32 
 33 }
 34 
 35 //显示图片信息
 36 
 37 -(void)displayProductImage
 38 
 39 {
 40 
 41     NSURL *url = [NSURL URLWithString:@"http://xxx.xxx.xxx.xxx"];
 42 
 43     //这个是从器返回有图片数目,self.xxxx根据具体的场合
 44 
 45     int imageCount = [self.xxxx.imageNum intValue];
 46 
 47     for (int i=0; i<imageCount; i++) {
 48 
 49         NSString *str1 = @"这里是拼图片请求url,根据实际需求";
 50 
 51         self.imageURL = [url URLByAppendingPathComponent:str1];
 52 
 53         //根据图片号请求资源
 54 
 55         [self displayImageByIndex:i ByImageURL:self.productImageURL];
 56 
 57     }
 58 
 59 }
 60 
 61 //根据图片序号显示请求图片资源
 62 
 63 -(void) displayImageByIndex:(NSInteger)index ByImageURL:(NSURL *)url
 64 
 65 {
 66 
 67     NSString *indexForString = [NSString stringWithFormat:@"%d",index];
 68 
 69     //若数组中已经存在该图片编号,说明图片加载完毕,直接返回
 70 
 71     if ([self.originalIndexArray containsObject:indexForString]) {
 72 
 73          return;
 74 
 75     }
 76 
 77     //创建UIImageView对象
 78 
 79     UIImageView *imageView = [[UIImageView alloc] init];
 80 
 81     imageView.tag = index;
 82 
 83     //创建资源请求对象
 84 
 85     ResourceContainer  *imageOperation = [[ResourceContainer alloc] init];
 86 
 87     imageOperation.resourceURL = url;
 88 
 89     imageOperation.hostObject = self;
 90 
 91     //设置收到图片信息处理理方法
 92 
 93     imageOperation.resourceDidReceive = @selector(imageDidReceive:);
 94 
 95     imageOperation.imageView = imageView;
 96 
 97     [imageView release];
 98 
 99     //将图片请求对象加入图片请求队列中
100 
101     [self.requsetImageQueue addOperation:imageOperation];
102 
103     [self.originalOperationDic setObject:imageOperation forKey:indexForString];
104 
105     [imageOperation release];
106 
107 }
108 
109 //处理图片请求返回信息
110 
111 -(void)imageDidReceive:(UIImageView *)imageView
112 
113 {
114 
115     if (imageView == nil||imageView.image == nil) {
116 
117             imageView.image = [UIImage imageNamed:@"no-pic-300-250.png"];
118 
119      }
120 
121     //将图片信息加载到前台,self.openFlowView是我用的coverFlow,coverFlow的使用方法网上很多,自己找吧
122 
123     [self.openFlowView setImage:imageView.image forIndex:imageView.tag];
124 
125     [self.originalIndexArray addObject:[NSString stringWithFormat:@"%d",imageView.tag]];
126 
127     [self.originalOperationDic removeObjectForKey:[NSString stringWithFormat:@"%d",imageView.tag]];
128 
129 }
130 
131 - (void)dealloc
132 
133 {
134      [_requestImageQueue release];
135 
136      [_originalIndexArray release];
137 
138      [_originalOperationDic release];
139 
140      [_imageURL release];
141 
142      [super dealloc];
143 
144 }
145 
146 @end
复制代码


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

你可能感兴趣的:(ios)