背景:
上一個(gè)項(xiàng)目中對(duì)AFN的二次封裝:是寫(xiě)一個(gè)單例的基類,基類持有AFN請(qǐng)求對(duì)象,具體的業(yè)務(wù)通過(guò)繼承基類來(lái)區(qū)分,不同的業(yè)務(wù)邏輯對(duì)應(yīng)著一個(gè)單例類,這樣隨著業(yè)務(wù)擴(kuò)大,單例逐漸增多;而有些功能之間的界限并沒(méi)有那么明顯,就產(chǎn)生了臃腫,邏輯不清晰等缺點(diǎn).重構(gòu)的話耗時(shí)耗力..
正好公司開(kāi)啟新的項(xiàng)目,有感于之前網(wǎng)絡(luò)請(qǐng)求的封裝模式不夠優(yōu)雅,專門(mén)對(duì)AFN進(jìn)行了一次封裝,改進(jìn)之前的弊端.
- 調(diào)用簡(jiǎn)單,接口優(yōu)雅.
- 可定制不同請(qǐng)求接口.
- 可控制請(qǐng)求頻率,同一個(gè)請(qǐng)求時(shí)間間隔.
- 請(qǐng)求未發(fā)送前,可取消請(qǐng)求.
- 若某個(gè)請(qǐng)求失敗,可配置重發(fā)次數(shù).
- 支持GET和POST
- 適合中小型,不需要很復(fù)雜網(wǎng)絡(luò)請(qǐng)求的項(xiàng)目可適用.
源碼GitHub,喜歡的同學(xué)給個(gè)? ?.
調(diào)用示例
- 對(duì)網(wǎng)絡(luò)請(qǐng)求中使用的參數(shù)進(jìn)行配置,只需要一次.
- (void)configHttpAPI {
[FGRequestCenter setupConfig:^(FGRequestConfig * _Nonnull config) {
//默認(rèn)的請(qǐng)求服務(wù)器地址...
config.generalServer = @"http:// ----- ";
//返回?cái)?shù)據(jù)的線程,若不設(shè)置,默認(rèn)子線程...
config.callbackQueue = dispatch_get_main_queue();
//路徑中拼接,與服務(wù)器約定的一些不會(huì)改動(dòng)的參數(shù),比如:渠道,系統(tǒng)版本...
config.generalParameters = @{
@"os":@"---",
@"channel":@"---",
@"osversion":@"---",
};
//路徑中拼接,與服務(wù)器約定的一些會(huì)改動(dòng)的參數(shù),比如:網(wǎng)絡(luò)狀態(tài),請(qǐng)求時(shí)間戳...
config.realTimeParametersBlock = ^NSDictionary * _Nonnull{
return @{
@"time":@"---",
@"network":@"---"
};
};
}];
}
- 常用,需要成功和失敗回調(diào)的示例
[FGRequestCenter sendRequest:^(FGRequestItem * _Nonnull item) {
//請(qǐng)求的路徑
item.api = k_auth_qqLogin;
//配置請(qǐng)求的參數(shù)
item.parameters = @{
@"666":@"999"
};
} onSuccess:^(id _Nullable responseObject) {
//成功回調(diào)
} onFailure:^(NSError * _Nullable error) {
//失敗回調(diào)
} onFinished:^(id _Nullable responseObject, NSError * _Nullable error) {
//請(qǐng)求完成回調(diào)(不論成功或失敗)
}];
- 不需要回調(diào)
[FGRequestCenter sendRequest:^(FGRequestItem * _Nonnull item) {
item.api = k_auth_qqLogin;
}];
- 只需要成功回調(diào)
[FGRequestCenter sendRequest:^(FGRequestItem * _Nonnull item) {
item.api = k_auth_qqLogin;
} onSuccess:^(id _Nullable responseObject) {
}];
- 只需要完成后的回調(diào)+可針對(duì)請(qǐng)求進(jìn)行定制示例
[FGRequestCenter sendRequest:^(FGRequestItem * _Nonnull item) {
item.api = k_auth_qqLogin;
//若此接口需要調(diào)用與默認(rèn)配置的服務(wù)器不同,可在此修改separateServer屬性
item.separateServer = @"----";
//請(qǐng)求的間隔,避免頻繁發(fā)送請(qǐng)求給服務(wù)器,默認(rèn)是:2s,如有需要單獨(dú)設(shè)置,也可修改默認(rèn)值
item.requestInterval = 2.f;
//如果在間隔內(nèi)發(fā)送請(qǐng)求,到時(shí)后是否繼續(xù)處理,默認(rèn)是NO,不做處理
item.isFrequentContinue = NO;
//失敗后重復(fù)次數(shù),默認(rèn)為0
item.retryCount = 1;
} onFinished:^(id _Nullable responseObject, NSError * _Nullable error) {
}];
- 取消請(qǐng)求,注意是在請(qǐng)求未發(fā)送前
NSString *identifier = [FGRequestCenter sendRequest:^(FGRequestItem * _Nonnull item) {
item.api = k_auth_qqLogin;
}];
[FGRequestCenter cancelRequest:identifier onCancel:^{
}];
- 更多使用請(qǐng)參考源碼.
架構(gòu)介紹
- FGRequestConfig: 請(qǐng)求配置類,比如默認(rèn)服務(wù)器,回調(diào)線程,請(qǐng)求參數(shù)等內(nèi)容.
- FGRequestItem: 針對(duì)每一個(gè)網(wǎng)絡(luò)請(qǐng)求封裝的模型類,通過(guò)對(duì)屬性的設(shè)置,可以對(duì)每個(gè)網(wǎng)絡(luò)請(qǐng)求進(jìn)行定制.
- FGRequestCenter: 對(duì)上層提供接口,調(diào)用下層方法.在這里操作:路徑拼接,請(qǐng)求配置,網(wǎng)絡(luò)狀態(tài)監(jiān)測(cè),請(qǐng)求處理等.
- FGRequestEngine: 對(duì)AFN的封裝,負(fù)責(zé)調(diào)用AFN發(fā)送請(qǐng)求.
控制請(qǐng)求間隔思路
在FGRequestCenter類中,持有一個(gè)pool形式的NSMutableDictionary , 每次收到發(fā)送的請(qǐng)求以keyValue的形式將請(qǐng)求的url和一下次允許請(qǐng)求的時(shí)間存起來(lái).下次調(diào)用前對(duì)pool進(jìn)行檢測(cè)是否允許請(qǐng)求,當(dāng)未滿足請(qǐng)求時(shí)間時(shí),判斷是否等待,再發(fā)送請(qǐng)求.并通過(guò)定時(shí)器輪詢的方式對(duì)pool內(nèi)的鍵值對(duì)進(jìn)行篩選,移除超時(shí)的keyValue.
使用技巧
因?yàn)榫W(wǎng)絡(luò)請(qǐng)求在項(xiàng)目中很多文件都會(huì)使用,如果item.api = @"/auth/login"這樣去寫(xiě),修改起來(lái)會(huì)很麻煩,我們可以在寫(xiě)個(gè)接口文件,統(tǒng)一將接口在文件中配置.若接口非常多,可以根據(jù)業(yè)務(wù)創(chuàng)建多個(gè)文件來(lái)區(qū)分.
總結(jié)
若有疑問(wèn)和Bug,歡迎留言,一定改進(jìn).