HTTP 請求Request參數(shù)設(shè)置, 請求的具體過程都已經(jīng)執(zhí)行完成,本篇來總結(jié) responseSerialization.
總的結(jié)構(gòu)
整個 response 解析的部分主要包括:
- protocol AFURLResponseSerialization
- 基類 AFHTTPResponseSerializer
- 多個子類:
AFJSONResponseSerializer;,AFXMLParserResponseSerializer,AFXMLDocumentResponseSerializer,AFPropertyListResponseSerializer,AFImageResponseSerializer, AFCompoundResponseSerializer
它們具體的關(guān)系圖如下:
從關(guān)系圖中可以看出他們之間的關(guān)系.AFURLResponseSerialization protocol 的方法主要將 response data 轉(zhuǎn)化成一個 id 類型的數(shù)據(jù), 這里具體轉(zhuǎn)化成何種數(shù)據(jù), 需要自己去定義 ,比如 AFNetworking 框架中已經(jīng)給出幾個: JSON對象, XML 對象, Image等等. AFHTTPResponseSerializer基類實現(xiàn)了AFURLResponseSerialization protocol 方法,并且實現(xiàn)解析數(shù)據(jù)之前的一個基本需求: 驗證 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"
,如果服務(wù)器的 response 中 ContentType 是"text/html",需要在這里添加.最好的方式是自己實現(xiàn)一個 AFXXXXResponseSerializer.
self.acceptableContentTypes = [NSSet setWithObjects:@"application/json", @"text/json", @"text/javascript", nil];
在實現(xiàn)responseObjectForResponse:data:error
方法中, 使用系統(tǒng)的NSJSONSerialization解析json荠锭,代碼中具體的數(shù)據(jù)格式變化: NSData->NSString->NSData->NSObject(主要是因為系統(tǒng)解析 json 的函數(shù)只支持 UTF-8格式).如果和服務(wù)器約定好使用 UTF-8格式傳遞數(shù)據(jù), 這里可以省略前兩步的轉(zhuǎn)換(自己繼承AFHTTPResponseSerializer, 自己實現(xiàn)一個 responseSerializer)寻拂。最后實現(xiàn)了方法刪除了 json 中的 nil 值.
圖片處理
bangs blog 中提到, 加載網(wǎng)絡(luò)圖片中可能出現(xiàn)的問題:
當我們調(diào)用UIImage的方法imageWithData:方法把數(shù)據(jù)轉(zhuǎn)成UIImage對象后,其實這時UIImage對象還沒準備好需要渲染到屏幕的數(shù)據(jù)估盘,現(xiàn)在的網(wǎng)絡(luò)圖像PNG和JPG都是壓縮格式车柠,需要把它們解壓轉(zhuǎn)成bitmap后才能渲染到屏幕上唯沮,如果不做任何處理,當你把UIImage賦給UIImageView堪遂,在渲染之前底層會判斷到UIImage對象未解壓介蛉,沒有bitmap數(shù)據(jù),這時會在主線程對圖片進行解壓操作溶褪,再渲染到屏幕上币旧。這個解壓操作是比較耗時的,如果任由它在主線程做猿妈,可能會導致速度慢UI卡頓的問題吹菱。
AFImageResponseSerializer除了把返回數(shù)據(jù)解析成UIImage外,還會把圖像數(shù)據(jù)解壓彭则,這個處理是在子線程(AFNetworking專用的一條線程鳍刷,詳見AFURLConnectionOperation),處理后上層使用返回的UIImage在主線程渲染時就不需要做解壓這步操作俯抖,主線程減輕了負擔输瓜,減少了UI卡頓問題。
具體實現(xiàn)上在AFInflatedImageFromResponseWithDataAtScale里芬萍,創(chuàng)建一個畫布尤揣,把UIImage畫在畫布上,再把這個畫布保存成UIImage返回給上層柬祠。只有JPG和PNG才會嘗試去做解壓操作北戏,期間如果解壓失敗,或者遇到CMKY顏色格式的jpg漫蛔,或者圖像太大(解壓后的bitmap太占內(nèi)存嗜愈,一個像素3-4字節(jié),搞不好內(nèi)存就爆掉了)莽龟,就直接返回未解壓的圖像蠕嫁。
這里可以參考 SDWebImage 的源碼分析.