1. 程式人生 > >基於AFNetworking3.X的二次封裝及拓展

基於AFNetworking3.X的二次封裝及拓展

AFN3.X其實已經很封裝的很好了,但是做專案的時候,總是有情況需要對網路統一處理,比如說快取策略、重複請求管理功能,這些AFN3.1都沒有提供直接的方法;比如每次請求回來,都有可能存在異常,我們肯定不能在每個請求裡都加判斷,所以就基於AFNetworking之上做了一層封裝,向業務層更加友好。

概述

ZBNetworking是一個集約型框架,發起請求集中在一個類上,統一管理,適合中小型的專案,需要對網路請求進行更加細緻的配置和管理,這個網路框架就可能不太適合,如果是大專案可以看一下YTKNetwork。框架目錄如下
ZBN目錄

重複請求

判斷是否是同一個請求(依據是請求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];

原始碼地址