基於AFNetworking3.X的二次封裝及拓展
AFN3.X其實已經很封裝的很好了,但是做專案的時候,總是有情況需要對網路統一處理,比如說快取策略、重複請求管理功能,這些AFN3.1都沒有提供直接的方法;比如每次請求回來,都有可能存在異常,我們肯定不能在每個請求裡都加判斷,所以就基於AFNetworking之上做了一層封裝,向業務層更加友好。
概述
ZBNetworking是一個集約型框架,發起請求集中在一個類上,統一管理,適合中小型的專案,需要對網路請求進行更加細緻的配置和管理,這個網路框架就可能不太適合,如果是大專案可以看一下YTKNetwork。框架目錄如下
重複請求
判斷是否是同一個請求(依據是請求url和引數是否相同)
1. GET:就判斷請求的URL是否相同,
2. POST:如果是POST請求,除了判斷URL,還需判斷請求體的內容是否相同(POST請求的引數放在HTTP body裡);
- (BOOL)isTheSameRequest:(NSURLRequest *)request {
if ([self.HTTPMethod isEqualToString:request.HTTPMethod]) {
if ([self.URL.absoluteString isEqualToString:request.URL.absoluteString]) {
if ([self.HTTPMethod isEqualToString:@"GET"] || [self.HTTPBody isEqualToData:request.HTTPBody ]) {
NSLog(@"同一個請求還沒執行完,又來請求☹️");
return YES;
}
}
}
return NO;
}
遍歷ZBNetworking當前的執行任務(調動currentRunningTasks獲取當前的執行任務),根據任務源請求判斷是否已經有相同的請求正在執行當中:
- (BOOL)haveSameRequestInTasksPool:(ZBURLSessionTask *)task {
__block BOOL isSame = NO ;
[[self currentRunningTasks] enumerateObjectsUsingBlock:^(ZBURLSessionTask *obj, NSUInteger idx, BOOL * _Nonnull stop) {
if ([task.originalRequest isTheSameRequest:obj.originalRequest]) {
isSame = YES;
*stop = YES;
}
}];
return isSame;
}
如果有重複請求,取消新請求
//判斷重複請求,如果有重複請求,取消新請求
if ([self haveSameRequestInTasksPool:session]) {
[session cancel];
return session;
}
網路回撥統一處理
可以在此方法裡,根據業務需要新增判斷
- (BOOL)networkResponseManage:(id)responseObject{
NSData *data = nil;
NSError *error = nil;
if ([responseObject isKindOfClass:[NSData class]]) {
data = responseObject;
}else if ([responseObject isKindOfClass:[NSDictionary class]]){
data = [NSJSONSerialization dataWithJSONObject:responseObject options:NSJSONWritingPrettyPrinted error:&error];
}
id json = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:&error];
NSLog(@"%@",json);
//統一判斷所有請求返回狀態,例如:-2就強制更新
int stat = 0;
switch (stat) {
case -1:{//強制退出
return NO;
}
break;
case -2:{//強制更新
return NO;
}
break;
case -3:{//彈出對話方塊
return NO;
}
break;
default:
break;
}
return YES;
}
快取設計
先說說如何啟動我們的快取機制,GET和POST的API有一個cache引數,它用於給大家決定是否開啟快取機制,你可以根據自己的需要來決定是否開啟cache,即時性和時效性的資料建議不開啟快取,一般建議開啟,開啟快取後會回撥兩次,第一次獲取是快取資料,第二次獲取的是最新的網路資料
NSURLCache的侷限性,需要基於HTTP快取機制的快取方案需要客戶端和伺服器雙邊配合。所以我學習SDWebImage的快取方案分兩級快取:記憶體快取和磁碟快取,快取的過程如下:
第一次請求獲取相應資料,先快取到記憶體,再快取到磁碟,下一次再發起相同的請求時,會先查詢記憶體之中會不會有相應的快取,如果有則返回快取資料,如果沒有,則向磁碟查詢,如果磁碟存在快取則返回,否則發起網路請求獲取資料。
上面就是快取的整一個過程,思路還是比較清晰,除此之外,快取的設計還需要考慮兩個問題:
1. 快取的淘汰策略
2. 快取的過期機制
ZBCacheManager是一個快取管理類,暴露出簡單的API給XDNetworking進行快取的存取,底層是使用ZBMemoryCache(NSCache)進行記憶體快取,使用ZBDiskCache(NSFileManager)進行磁碟快取,快取淘汰策略採用LRU演算法(ZBLRUManager)。它是一個單例,通過一個全域性入口統一訪問:
+ (ZBCacheManager *)shareManager;
預設是磁碟大小是50MB,有效期是7天,如果想自定義設定,可以通過以下方法設定:
- (void)setCacheTime:(NSTimeInterval) time diskCapacity:(NSUInteger) capacity;
API設計
GET請求
/**
* GET請求
*
* @param url 請求路徑
* @param cache 是否快取
* @param params 拼接引數
* @param progressBlock 進度回撥
* @param successBlock 成功回撥
* @param failBlock 失敗回撥
*
* @return 返回的物件中可取消請求
*/
- (ZBURLSessionTask *)getWithUrl:(NSString *)url
cache:(BOOL)cache
params:(NSDictionary *)params
progressBlock:(ZBGetProgress)progressBlock
successBlock:(ZBResponseSuccessBlock)successBlock
failBlock:(ZBResponseFailBlock)failBlock;
POST請求
/**
* POST請求
*
* @param url 請求路徑
* @param cache 是否快取
* @param refresh 解釋同上
* @param params 拼接引數
* @param progressBlock 進度回撥
* @param successBlock 成功回撥
* @param failBlock 失敗回撥
*
* @return 返回的物件中可取消請求
*/
- (ZBURLSessionTask *)postWithUrl:(NSString *)url
refreshRequest:(BOOL)refresh
cache:(BOOL)cache
params:(NSDictionary *)params
progressBlock:(ZBPostProgress)progressBlock
successBlock:(ZBResponseSuccessBlock)successBlock
failBlock:(ZBResponseFailBlock)failBlock;
檔案上傳
/**
* 檔案上傳
*
* @param url 上傳檔案介面地址
* @param data 上傳檔案資料
* @param type 上傳檔案型別
* @param name 上傳檔案伺服器資料夾名
* @param mimeType mimeType
* @param progressBlock 上傳檔案路徑
* @param successBlock 成功回撥
* @param failBlock 失敗回撥
*
* @return 返回的物件中可取消請求
*/
- (ZBURLSessionTask *)uploadFileWithUrl:(NSString *)url
fileData:(NSData *)data
type:(NSString *)type
name:(NSString *)name
mimeType:(NSString *)mimeType
progressBlock:(ZBUploadProgressBlock)progressBlock
successBlock:(ZBResponseSuccessBlock)successBlock
failBlock:(ZBResponseFailBlock)failBlock;
多檔案上傳
/**
* 多檔案上傳
*
* @param url 上傳檔案地址
* @param datas 資料集合
* @param type 型別
* @param name 伺服器資料夾名
* @param mimeTypes mimeTypes
* @param progressBlock 上傳進度
* @param successBlock 成功回撥
* @param failBlock 失敗回撥
*
* @return 任務集合
*/
- (NSArray *)uploadMultFileWithUrl:(NSString *)url
fileDatas:(NSArray *)datas
type:(NSString *)type
name:(NSString *)name
mimeType:(NSString *)mimeTypes
progressBlock:(ZBUploadProgressBlock)progressBlock
successBlock:(ZBMultUploadSuccessBlock)successBlock
failBlock:(ZBMultUploadFailBlock)failBlock;
檔案下載
/**
* 檔案下載
*
* @param url 下載檔案介面地址
* @param progressBlock 下載進度
* @param successBlock 成功回撥
* @param failBlock 下載回撥
*
* @return 返回的物件可取消請求
*/
- (ZBURLSessionTask *)downloadWithUrl:(NSString *)url
progressBlock:(ZBDownloadProgress)progressBlock
successBlock:(ZBDownloadSuccessBlock)successBlock
failBlock:(ZBDownloadFailBlock)failBlock;
獲取當前正在執行的任務
/**
* 正在執行的網路任務
* @return task
*/
- (NSArray *)currentRunningTasks;
取消GET請求
/**
* 取消GET請求
*/
- (void)cancelRequestWithURL:(NSString *)url;
取消所有請求
/**
* 取消所有請求
*/
- (void)cancleAllRequest;
獲取快取大小
/**
* 獲取快取大小
*
* @return 快取大小
*/
- (NSUInteger)totalCacheSize;
清除下載資料
/**
* 清除下載資料
*/
- (void)clearDownloadData;
清除所有快取
/**
* 清除所有快取
*/
- (void)clearTotalCache;
自動清理快取
//每次網路請求的時候,檢查此時磁碟中的快取大小,閾值預設是50MB,如果超過閾值,則清理LRU緩
//存,同時也會清理過期快取,快取預設SSL是7天,磁碟快取的大小和SSL的設定可以通過該方法
//[YQCacheManager shareManager] setCacheTime: diskCapacity:]設定。
[[ZBCacheManager shareManager] clearLRUCache];