AFNetworking 2.x 阅读笔记(五)

HTTP 请求Request参数设置, 请求的具体过程都已经执行完成,本篇来总结 responseSerialization.

总的结构

整个 response 解析的部分主要包括:

  • protocol AFURLResponseSerialization
  • 基类 AFHTTPResponseSerializer
  • 多个子类:
    AFJSONResponseSerializer;,AFXMLParserResponseSerializer,AFXMLDocumentResponseSerializer,AFPropertyListResponseSerializer,AFImageResponseSerializer, AFCompoundResponseSerializer

它们具体的关系图如下:

AFNetworking 2.x 阅读笔记(五)_第1张图片
requestResponse.png

从关系图中可以看出他们之间的关系.AFURLResponseSerialization protocol 的方法主要将 response data 转化成一个 id 类型的数据, 这里具体转化成何种数据, 需要自己去定义 ,比如 AFNetworking 框架中已经给出几个: JSON对象, XML 对象, Image等等. AFHTTPResponseSerializer基类实现了AFURLResponseSerialization protocol 方法,并且实现解析数据之前的一个基本需求: 验证 response 对象的合法性, 包括 response status code 和 content type.

/**
 The response object decoded from the data associated with a specified response.

 @param response The response to be processed.
 @param data The response data to be decoded.
 @param error The error that occurred while attempting to decode the response data.

 @return The object decoded from the specified response data.
 */
- (nullable id)responseObjectForResponse:(nullable NSURLResponse *)response
                           data:(nullable NSData *)data
                          error:(NSError * __nullable __autoreleasing *)error


/**
 Validates the specified response and data.

 In its base implementation, this method checks for an acceptable status code and 
content type. Subclasses may wish to add other domain-specific checks.

 @param response The response to be validated.
 @param data The data associated with the response.
 @param error The error that occurred while attempting to validate the response.

 @return `YES` if the response is valid, otherwise `NO`.
 */
- (BOOL)validateResponse:(nullable NSHTTPURLResponse *)response
                    data:(nullable NSData *)data
                   error:(NSError * __nullable __autoreleasing *)error;

JSONResposneSerializer 将 json -> object

选取一个代表性的子类AFJSONResponseSerializer

在初始化对象时候,声明接受的 ContentType 的类型只有@"application/json", @"text/json", @"text/javascript",如果服务器的 response 中 ContentType 是"text/html",需要在这里添加.最好的方式是自己实现一个 AFXXXXResponseSerializer.

self.acceptableContentTypes = [NSSet setWithObjects:@"application/json", @"text/json", @"text/javascript", nil];

在实现responseObjectForResponse:data:error方法中, 使用系统的NSJSONSerialization解析json,代码中具体的数据格式变化: NSData->NSString->NSData->NSObject(主要是因为系统解析 json 的函数只支持 UTF-8格式).如果和服务器约定好使用 UTF-8格式传递数据, 这里可以省略前两步的转换(自己继承AFHTTPResponseSerializer, 自己实现一个 responseSerializer)。最后实现了方法删除了 json 中的 nil 值.

图片处理

bangs blog 中提到, 加载网络图片中可能出现的问题:
当我们调用UIImage的方法imageWithData:方法把数据转成UIImage对象后,其实这时UIImage对象还没准备好需要渲染到屏幕的数据,现在的网络图像PNG和JPG都是压缩格式,需要把它们解压转成bitmap后才能渲染到屏幕上,如果不做任何处理,当你把UIImage赋给UIImageView,在渲染之前底层会判断到UIImage对象未解压,没有bitmap数据,这时会在主线程对图片进行解压操作,再渲染到屏幕上。这个解压操作是比较耗时的,如果任由它在主线程做,可能会导致速度慢UI卡顿的问题。
AFImageResponseSerializer除了把返回数据解析成UIImage外,还会把图像数据解压,这个处理是在子线程(AFNetworking专用的一条线程,详见AFURLConnectionOperation),处理后上层使用返回的UIImage在主线程渲染时就不需要做解压这步操作,主线程减轻了负担,减少了UI卡顿问题。
具体实现上在AFInflatedImageFromResponseWithDataAtScale里,创建一个画布,把UIImage画在画布上,再把这个画布保存成UIImage返回给上层。只有JPG和PNG才会尝试去做解压操作,期间如果解压失败,或者遇到CMKY颜色格式的jpg,或者图像太大(解压后的bitmap太占内存,一个像素3-4字节,搞不好内存就爆掉了),就直接返回未解压的图像。

这里可以参考 SDWebImage 的源码分析.

你可能感兴趣的:(AFNetworking 2.x 阅读笔记(五))