1. 程式人生 > >UIImageView非同步載入網路圖片

UIImageView非同步載入網路圖片

方法1:在UI執行緒中同步載入網路圖片

    UIImageView *headview = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 40, 40)];
    
    NSURL *photourl = [NSURL URLWithString:@"http://www.exampleforphoto.com/pabb/test32.png"];
    //url請求實在UI主執行緒中進行的
    UIImage *images = [UIImage imageWithData:[NSData dataWithContentsOfURL:photourl]];//通過網路url獲取uiimage
    headview.image = images;
這是最簡單的,但是由於在主執行緒中載入,會阻塞UI主執行緒。所以可以試試NSOperationQueue,一個NSOperationQueue 操作佇列,就相當於一個執行緒管理器,而非一個執行緒。因為你可以設定這個執行緒管理器內可以並行執行的的執行緒數量等等。

------------------------------------------------------------------------------------------------

方法2:使用NSOperationQueue非同步載入

下面就是使用NSOperationQueue實現子執行緒載入圖片:
- (void)viewDidLoad
{
    [super viewDidLoad];
    
    NSOperationQueue *operationQueue = [[NSOperationQueue alloc] init];
    
    self.imageview  = [[[UIImageView alloc] initWithFrame:CGRectMake(110, 50, 100, 100)] autorelease];
    [self.imageview setBackgroundColor:[UIColor grayColor]];
    [self.view addSubview:self.imageview];
    
    NSInvocationOperation *op = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(downloadImage) object:nil];
    [operationQueue addOperation:op];
}

- (void)downloadImage
{
    NSURL *imageUrl = [NSURL URLWithString:HEADIMAGE_URL];
    UIImage *image = [UIImage imageWithData:[NSData dataWithContentsOfURL:imageUrl]];
    self.imageview.image = image;
}
不過這這樣的設計,雖然是非同步載入,但是沒有快取圖片。重新載入時又要重新從網路讀取圖片,重複請求,實在不科學,所以可以考慮第一次請求時儲存圖片。

------------------------------------------------------------------------------------------------

方法3:非同步載入,儲存到cache裡,下次再請求時讀取cache裡的快取圖片

3-1,首先在http請求時,建立一個快取目錄

            NSArray *paths =NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
            NSLog(@"the paths:%@",paths);
            NSString * diskCachePath = [[paths objectAtIndex:0] stringByAppendingPathComponent:@"imageCache"];
            NSLog(@"diskCachePath:%@",diskCachePath);
            
            //如果目錄imageCache不存在,建立目錄
            if (![[NSFileManager defaultManager] fileExistsAtPath:diskCachePath]) {
                NSError *error=nil;
                [[NSFileManager defaultManager] createDirectoryAtPath:diskCachePath withIntermediateDirectories:YES attributes:nil error:&error];
                
            }

3-2建立好目錄後,第一次時,url請求網路圖片,然後把得到的data儲存到本地cache裡。
          NSURL *headurl = [NSURL URLWithString:
@"http://hiweibo-common.stor.sinaapp.com/user_photo_34.png"]; 
// UIImage *headimg = [UIImage imageWithData:[NSData dataWithContentsOfURL:headurl]]; NSData *imagedata = [NSData dataWithContentsOfURL:headurl]; //如果本地快取沒有,儲存圖片 NSString *localPath = [NSString stringWithFormat:@"%@/headimage.png",diskCachePath];// NSLog(@"localpaht:%@",localPath); if (imagedata) { if (![[NSFileManager defaultManager] fileExistsAtPath:localPath]) { [[NSFileManager defaultManager] createFileAtPath:localPath contents:imagedata attributes:nil]; //[imagedata writeToFile:localPath atomically:YES];//也可以data write到file裡 } UIImage *headimg = [[UIImage alloc] initWithData:imagedata]; self.headimage = headimg; [headimg release]; [meTableView reloadData]; } 3-3然後在下一次開啟,初始化設定圖片的地方,判斷cache裡有沒有快取圖片,有的話直接載入。
    NSArray *paths =NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
    
    NSString *localpath = [[paths objectAtIndex:0] stringByAppendingPathComponent:@"/imageCache/headimage.png"];
    
    //如果有快取圖片,直接讀取cache內的快取圖片
    if ([[NSFileManager defaultManager] fileExistsAtPath:localpath]) {
        NSData *data = [NSData dataWithContentsOfFile:localpath];

        
        self.headimage = [UIImage imageWithData:data];
        [meTableView reloadData];
        
    }
    else{
        //如果沒有快取圖片,請求
        NSMutableDictionary *headdict =[NSMutableDictionary dictionaryWithObjectsAndKeys:tokenString,@"token",uidString,@"userid",nil];
        [self handlerPostFormDataWithParams:headdict withURL:APPROVAL_URL_GETPHOTO];
    }

方法3是最科學的,只需要一次讀取,以後就可以直接用了。

目前總結到這裡,以後有更深入研究時再補充

20130314