QF——網絡之網絡請求的幾種方式,圖片緩存

同步請求和異步請求:json

   同步請求會阻塞主線程;不會開啓新的線程,仍是主線程,因此直到請求成功後,才能執行其它操做。api

   異步請求不會阻塞主線程。開啓新的線程去請求服務器,而不影響用戶的交互操做等其餘動做。緩存

 

使用NSURLConnection發送同步請求和異步請求:性能優化

同步請求:服務器

異步請求:(block回調方式)——請求的數據經過block返回網絡

 

 

異步請求:(delegate方式)——請求的數據在重寫的代理方法裏返回app

 須要注意的是:框架

- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
didReceiveData的參數data是從服務器返回的二進制數據,因此咱們使用NSMutableData類型來接收。所以,json解析的核心就是把從網絡而來的二進制數據(NSData)轉換爲json對象。而後從json結構獲取有意義的數據。
NSDictionary * jsonDict = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:&error];

補充:網絡請求返回的數據通常都是二進制數據(NSData),但若請求是純文檔,則也可使用NSString接收。異步

 

 

//
//  ViewController.m
//  JSONTest
//
//  Created by mac on 15-3-30.
//  Copyright (c) 2015年 ___FULLUSERNAME___. All rights reserved.
//

#import "ViewController.h"
#import "App.h"
#import "UIImageView+WebCache.h"
#define kSearchUrl @"https://api.douban.com/v2/book/search?q=s"

@interface ViewController ()<UITableViewDataSource,UITableViewDelegate,NSURLConnectionDataDelegate,NSURLConnectionDelegate>
{
    NSMutableArray * appArr;
    NSMutableData * downloadData;
    
    UITableView * tabView;
}

@end

@implementation ViewController
- (void)viewDidLoad
{
    [super viewDidLoad];
    
    downloadData = [NSMutableData data];
    appArr = [NSMutableArray array];
    
    //新建tableView
    [self createTableView];
    
    //創建異步請求
    [self makeConnection];
    
    
    
}

- (void)createTableView
{
    tabView = [[UITableView alloc]initWithFrame:CGRectMake(0, 0, 320, 480) style:UITableViewStyleGrouped];
    tabView.delegate = self;
    tabView.dataSource = self;
    tabView.rowHeight = 80;
    [self.view addSubview:tabView];
    
//    [tabView registerClass:[UITableViewCell class] forCellReuseIdentifier:@"cell"];
    
}

- (void)makeConnection
{
    [NSURLConnection connectionWithRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:kSearchUrl]] delegate:self];
    
}

- (void)decodeJson:(NSMutableData *)data
{
    NSError * error;
    NSDictionary * jsonDict = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:&error];
    NSArray * jsonArr = jsonDict[@"books"];
    for(NSDictionary * dict1 in jsonArr)
    {
        NSString * large = dict1[@"images"][@"large"];
        NSString * title = dict1[@"title"];
        NSString * author = dict1[@"author"][0];
        
        App * app = [[App alloc]init];
        app.large = large;
        app.title = title;
        app.author = author;
        
        [appArr addObject:app];
    }
    
    NSLog(@"%d",appArr.count);
   
    
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return appArr.count;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    UITableViewCell * cell = [tableView dequeueReusableCellWithIdentifier:@"cell"];
    if(cell==nil)
    {
        cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:@"cell"];
        
        if(appArr.count>0)
        {
            App * app = appArr[indexPath.row];
            cell.textLabel.text = app.title;
            cell.detailTextLabel.text = app.author;
            [cell.imageView sd_setImageWithURL:[NSURL URLWithString:app.large] placeholderImage:[UIImage imageNamed:@"photo"]];
        }
    }
    
    return cell;
}


- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
    downloadData.length = 0;
}

- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
    [downloadData appendData:data];
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
    //解析json數據
    [self decodeJson:downloadData];
    [tabView reloadData];
    
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
    NSLog(@"%@",error);
}


- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
}

@end

 

使用第三方網絡請求框架AFNetworking:性能

  先實例化出一個manager對象,對網絡的GET和POST請求都是經過它的方法完成的。

  success的block返回值responseObject就是服務器傳過來的完整數據。返回的數據類型默認是json格式的。它的強大不只在於高度封裝了對網絡的請求,並且能夠根據不一樣情形設置請求數據和返回數據的格式。它默認的請求數據類型爲二進制的,默認的返回數據類型爲json。若請求的服務器是json文檔,則返回的直接就是json數據,直接獲取有意義的數據就行;若請求的服務器是xml文檔,則先要使其返回數據類型爲xml格式的。

 

  能夠在success的block裏完成數據解析。

    AFHTTPRequestOperationManager * manager = [AFHTTPRequestOperationManager manager];
    [manager GET:kSearchUrl parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) {
        NSLog(@"請求成功");
        //responseObject就是傳過來的數據,並且是一次性完整的數據。能夠在這裏完成數據解析工做
    } failure:^(AFHTTPRequestOperation *operation, NSError *error) {
        NSLog(@"請求失敗");
    }];

 補充:

manager 的POST請求有兩個方法,上面是下載,還有一個用於上傳。

參數formData就是要上傳的數據。

 

圖片緩存問題:(性能優化)

  上面的代碼用到了一個很是優秀的第三方框架SDWebImage。它會自動實現異步加載,圖片緩存,控制同一URL加載次數(同一個url不會重複請求)

  [cell.imageView sd_setImageWithURL:[NSURL URLWithString:app.large] placeholderImage:[UIImage imageNamed:@"photo"]];

該句就是核心代碼,它自動會幫咱們實現圖片緩存。並且在第一次去服務器加載圖片還沒獲取到時,是用佔位圖片的(placeholderImage),等從服務器加載到了圖片後就被替換掉了 

  設想,要是在加載圖片的時候咱們不使用SDWebImage框架,那連咱們滑動tableView時,只要滑出現一次就會去服務器加載一次,這無疑是很糟糕的,太費流量和時間了。此時咱們的策略是使用圖片緩存,首先判斷有沒有緩存,如有緩存,則用緩存的圖片;若無緩存,纔去服務器加載。緩存則分爲內存緩存和本地緩存。內存緩存是不理想的,由於它比較佔用內存,影響APP運行速度。其次內存緩存只存在於APP一個運行週期裏,當關閉APP時,內存緩存會清空,下次打開APP時,又得去服務器加載圖片。面對這樣的問題,咱們一般都採用本地緩存,也就是第一次從服務器把圖片加載後,寫入本地文件,那之後再次打開時,只要讀取本地文件的圖片就能夠了,這樣減小了請求服務器的次數,既下降了流量的消耗,又提高了性能。

相關文章
相關標籤/搜索