• QF——网络之网络请求的几种方式,图片缓存


    同步请求和异步请求:

       同步请求会阻塞主线程;不会开启新的线程,还是主线程,所以直到请求成功后,才能执行其它操作。

       异步请求不会阻塞主线程。开启新的线程去请求服务器,而不影响用户的交互操作等其他动作。

    使用NSURLConnection发送同步请求和异步请求:

    同步请求:

    异步请求:(block回调方式)——请求的数据通过block返回

    异步请求:(delegate方式)——请求的数据在重写的代理方法里返回

     需要注意的是:

    - (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时,又得去服务器加载图片。面对这样的问题,我们通常都采用本地缓存,也就是第一次从服务器把图片加载后,写入本地文件,那以后再次打开时,只要读取本地文件的图片就可以了,这样减少了请求服务器的次数,既降低了流量的消耗,又提升了性能。

  • 相关阅读:
    【mac】homebrew国内源安装加速
    【Mac】快速删除指定文件夹下的.DS_Store文件
    【mac】Mac微信小助手安装和卸载
    如何高效的开展app的性能测试
    什么是C#?什么是DOTNET?
    Xamarin Android使用自签名证书
    产品经理的私房菜
    java并发编程2-Synchronized关键字底层实现原理详解
    VS Code 1.60 发布!竟然可以自动检测编程语言了!
    为什么'x1B'.length===1?x与u知识延伸
  • 原文地址:https://www.cnblogs.com/wangerxiansheng/p/4380242.html
Copyright © 2020-2023  润新知