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


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

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

    AD:

    在我们实际工程中,很多情况需要从网络上加载图片,然后将图片在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.      [_window release]; 
    49.   
    50.      [_downloadCache release]; 
    51.   
    52.     [super dealloc]; 
    53.   
    54.  } 
    55.   
    56.  @end 

    二、创建缓存线程

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

    ResourceContainer.h文件实现:

    1. #import <Foundation/Foundation.h> 
    2.   
    3.   #import "ASIHTTPRequest.h" 
    4.   
    5. #import "SplitDemoAppDelegate.h" 
    6.  
    7.  @interface ResourceContainer : NSOperation { 
    8.  
    9. NSURL*_resourceURL;            //资源请求url 
    10.   
    11.  NSObject*_hostObject;              
    12.  
    13.  SEL_resourceDidReceive;      //资源接手响应方法   
    14.  
    15.  SplitDemoAppDelegate*_appDelegate;            //应用委托对象 
    16.   
    17.  ASIHTTPRequest*_httpRequest;             
    18.   
    19.  UIImageView*_imageView;               
    20.  
    21.  } 
    22.   
    23.  
    24.  
    25.  @property (nonatomic, retain) NSURL*resourceURL; 
    26.  
    27. @property (nonatomic, retain) NSObject*hostObject; 
    28.  
    29.  @property (nonatomic, assign) SELresourceDidReceive; 
    30.   
    31.  @property (nonatomic, assign) SplitDemoAppDelegate   *appDelegate; 
    32.   
    33.  @property (nonatomic, retain) ASIHTTPRequest*httpRequest; 
    34.  
    35.  @property (nonatomic, retain) UIImageView*imageView; 
    36.  
    37.    
    38.  
    39.  //http请求回调方法 
    40.  
    41.  -(void)didStartHttpRequest:(ASIHTTPRequest *)request; 
    42.   
    43.  -(void)didFinishHttpRequest:(ASIHTTPRequest *)request; 
    44.  
    45.  -(void)didFailedHttpRequest:(ASIHTTPRequest *)request; 
    46.   
    47.   
    48.  
    49. //取消资源请求 
    50.  
    51.  -(void)cancelReourceGet; 
    52.   
    53.  //资源接收回调方法 
    54.  
    55.  -(void)resourceDidReceive:(NSData *)resource; 
    56.  
    57.  @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.  -(void)didStartHttpRequest:(ASIHTTPRequest *)request{ 
    64.   
    65.   [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:YES]; 
    66.  
    67.   } 
    68.  
    69.   //请求成功返回处理结果 
    70.  
    71.   -(void)didFinishHttpRequest:(ASIHTTPRequest *)request{ 
    72.   
    73.  [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO]; 
    74.   
    75.    
    76.  
    77.      if([request responseStatusCode] == 200 || [request responseStatusCode] == 304){ 
    78.  
    79.  //判断是否来自缓存 
    80.  
    81.          if([request didUseCachedResponse]){ 
    82.   
    83.   NSLog(@"=========资源请求:%@ 来自缓存============",[self.resourceURL absoluteURL]); 
    84.    
    85.         } 
    86.          else{ 
    87.              NSLog(@"=========资源请求:图片不来自缓存============"); 
    88.         } 
    89.   
    90.   
    91.       [self resourceDidReceive:[request responseData]]; 
    92.  
    93.  } 
    94.   
    95.  else { 
    96.  
    97.         [self resourceDidReceive:nil]; 
    98.  
    99.         } 
    100.  
    101.   
    102.  //失败请求返回处理结果 
    103.  
    104.  -(void)didFailedHttpRequest:(ASIHTTPRequest *)request{ 
    105.  
    106. [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO]; 
    107.   
    108.  [self resourceDidReceive:nil]; 
    109.  
    110.  
    111. //取消资源请求 
    112.  
    113.  -(void)cancelReourceGet{ 
    114.  
    115.  [self.httpRequest cancel]; 
    116.  
    117.  } 
    118.  
    119.  //资源接收处理方法 
    120.  
    121.  -(void)resourceDidReceive:(NSData *)resource{ 
    122.  
    123.  if([self.hostObject respondsToSelector:self.resourceDidReceive]){ 
    124.  
    125.  if(resource != nil && self.imageView != nil){ 
    126.  
    127.  self.imageView.image = [UIImage imageWithData:resource]; 
    128.  
    129.  
    130.   
    131.  [self.hostObject performSelectorOnMainThread:self.resourceDidReceive withObject:self.imageViewwaitUntilDone:NO]; 
    132.   
    133.   
    134.  } 
    135.  
    136.  @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. @property (nonatomic, retain) NSURL                       *imageURL; 
    15.  @property (nonatomic, retain) NSMutableArray          *originalIndexArray; 
    16.  @property (nonatomic, retain) NSMutableDictionary   *originalOperationDic; 
    17.  @property (nonatomic, retain) NSOperationQueue      * requestImageQueue; 
    18.  
    19.  //显示图片信息 
    20.   
    21.  -(void)displayProductImage; 
    22.   
    23. //根据图片序号显示请求图片资源 
    24.   
    25.  -(void)displayImageByIndex:(NSInteger)index ByImageURL:(NSURL *)url; 
    26.   
    27.  //处理图片请求返回信息 
    28.  
    29.  -(void)imageDidReceive:(UIImageView *)imageView; 
    30.  
    31.  @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.  -(void)imageDidReceive:(UIImageView *)imageView 
    111.  
    112.  { 
    113.  
    114.      if (imageView == nil||imageView.image == nil) { 
    115.  
    116.             imageView.image = [UIImage imageNamed:@"no-pic-300-250.png"]; 
    117.  
    118.      } 
    119.   
    120.      //将图片信息加载到前台,self.openFlowView是我用的coverFlow,coverFlow的使用方法网上很多,自己找吧 
    121.  
    122.      [self.openFlowView setImage:imageView.image forIndex:imageView.tag]; 
    123.  
    124.     [self.originalIndexArray addObject:[NSString stringWithFormat:@"%d",imageView.tag]]; 
    125.  
    126.     [self.originalOperationDic removeObjectForKey:[NSString stringWithFormat:@"%d",imageView.tag]]; 
    127.  
    128.  } 
    129.  
    130. - (void)dealloc 
    131.  
    132.  { 
    133.       [_requestImageQueue release]; 
    134.   
    135.      [_originalIndexArray release]; 
    136.  
    137.      [_originalOperationDic release]; 
    138.  
    139.      [_imageURL release]; 
    140.  
    141.      [super dealloc]; 
    142.  
    143.  
    144. @end 

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

    经验总结。本书共17章,

     
  • 相关阅读:
    学习路线
    环境搭建时用到的文档
    商城技术重点分析
    svn 忽略文件
    实用的css3 学习笔记
    转载 《AngularJS》5个实例详解Directive(指令)机制
    php 单例设计模式 example
    html5 图片转base64预览显示
    curl返回常见错误码
    jquery的end(),addBack()方法example
  • 原文地址:https://www.cnblogs.com/OIMM/p/4941507.html
Copyright © 2020-2023  润新知