• 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章,

     
  • 相关阅读:
    【转载】SAP_ECC6.0_EHP4或SAP_ECC6.0_EHP5_基于Windows_Server_2008R2_和SQL_server_2008下的安装
    使用delphi 开发多层应用(二十四)KbmMW 的消息方式和创建WIB节点
    使用delphi 开发多层应用(二十三)KbmMW 的WIB
    实现KbmMw web server 支持https
    KbmMW 服务器架构简介
    Devexpress VCL Build v2014 vol 14.1.1 beta发布
    使用delphi 开发多层应用(二十二)使用kbmMW 的认证管理器
    KbmMW 4.50.00 测试版发布
    Basic4android v3.80 beta 发布
    KbmMW 认证管理器说明(转载)
  • 原文地址:https://www.cnblogs.com/OIMM/p/4941507.html
Copyright © 2020-2023  润新知