網(wǎng)絡(luò)框架的封裝(一):第一層參數(shù)組裝層的API設(shè)計(jì)

什么是分層

app的架構(gòu),不管是MVC,MVP,MVVM,架構(gòu)演變中,貫穿始終的概念都是分層和解耦.那么這個(gè)分層和解耦怎么體現(xiàn)出來(lái)?
簡(jiǎn)單地說(shuō)就是,我這一層接收上一層的輸入,上一層的你別管我怎么處理,我最終會(huì)給你一個(gè)輸出/返回值,你完全不用理會(huì)我是怎么處理的,只要有輸入,就會(huì)有輸出,而且一般是通過(guò)一個(gè)簡(jiǎn)單的方法的調(diào)用來(lái)實(shí)現(xiàn).

那么,對(duì)于app中常用的網(wǎng)絡(luò)層來(lái)說(shuō),怎么樣的封裝才是最合理的?

我們的口號(hào)是:一行代碼完成網(wǎng)絡(luò)請(qǐng)求!

其實(shí)非常簡(jiǎn)單,看接口文檔你就知道了怎么做了:就傳那些個(gè)參數(shù),返回就是那個(gè)json之類的.把接口文檔轉(zhuǎn)化為我們調(diào)用的一個(gè)方法,這網(wǎng)絡(luò)層與上層的接口就可以說(shuō)是設(shè)計(jì)好了.

最常見(jiàn)的字符流請(qǐng)求:

接口文檔寫了什么:(百度圖片隨便找的一個(gè))

所以,我們網(wǎng)絡(luò)層應(yīng)該封裝成這樣一個(gè)方法:

傳入:

請(qǐng)求方式,url路徑,請(qǐng)求的參數(shù)key和值
注: 對(duì)于多個(gè)POST請(qǐng)求參數(shù)key-value,有的接口會(huì)定義成Map形式,有的會(huì)定義成Json形式.其實(shí)本質(zhì)上都是一樣的,都是在requestBody上POST一個(gè)字符串(字符流)出去,只不過(guò)前者的形式是a=4&t=5的形式,而后者是一個(gè)json形式.
總體上來(lái)講,還是前者比較多見(jiàn),畢竟參數(shù)拼接形式與GET請(qǐng)求一致,服務(wù)器端處理比較方便.

輸出/返回:

對(duì)于返回字符流數(shù)據(jù)的情況,可以歸納為返回一個(gè)String對(duì)象,怎么處理就看具體情況了.

app中常見(jiàn)的是返回json格式的字符串.當(dāng)然,一般app里需要的是解析好的javabean,那么網(wǎng)絡(luò)框架接口應(yīng)該能直接返回一個(gè)解析好的javabean.

當(dāng)然,更進(jìn)一步來(lái)看,大多數(shù)規(guī)范的api(看看各大api市場(chǎng),比如聚合api之類的)返回的json格式都具備以下特點(diǎn):

一般為三個(gè)字段,分別表示狀態(tài)碼,相關(guān)提示信息,以及一個(gè)用于攜帶數(shù)據(jù)的字段.(比如:{"code":0,"msg":"登錄成功","data":{...}}).攜帶數(shù)據(jù)的字段可以攜帶任何類型的數(shù)據(jù),null,數(shù)字,字符串,jsonObject,JsonArray都可以.
在這里,我把這種三個(gè)字段的json稱為"標(biāo)準(zhǔn)格式的json"

封裝好的方法:

getString(String url, Map map, MyNetListener listener)//get請(qǐng)求,返回一個(gè)string,拿到這個(gè)string
postString( String url,  Map map,  MyNetListener listener)

getCommonJson(String url, Map map, Class clazz, MyNetListener listener)//get請(qǐng)求,返回一個(gè)json,將整個(gè)json解析成javabean
postCommonJson(String url, Map map, Class clazz, MyNetListener listener)

getStandardJson(String url, Map map, Class clazz, MyNetListener listener)//get請(qǐng)求,返回一個(gè)標(biāo)準(zhǔn)格式的json
postStandardJson(String url, Map map, Class clazz, MyNetListener listener) //post請(qǐng)求,返回一個(gè)標(biāo)準(zhǔn)格式的json,通過(guò)傳入的clazz,直接解析返回data字段的javabean

//如果參數(shù)以json形式發(fā)出,那么再調(diào)用方法setParamsAsJson()即可.

上傳和下載

下載:

一般是GET請(qǐng)求,傳入url.請(qǐng)求參數(shù)可有可無(wú).最終下載得到一個(gè)文件(路徑可預(yù)先指定),并且在下載的過(guò)程中有進(jìn)度的回調(diào).
注意: 我上面一層不需要知道你的什么網(wǎng)絡(luò)流啊,斷點(diǎn)下載啊,分片多線程下載之類的細(xì)節(jié).

download(String url, String savedpath, MyNetListener callback)

上傳

POST請(qǐng)求,傳入url,請(qǐng)求參數(shù),文件相關(guān)的key名,文件的地址,最終返回一個(gè)結(jié)果(成功或失敗),并且在上傳的過(guò)程中有進(jìn)度回調(diào).
同樣的,上一層不需要知道里面具體的header設(shè)置啊,斷點(diǎn)續(xù)傳啊,分片上傳之類的細(xì)節(jié).
注意: http是支持多文件上傳的.

upLoad(String url, Map<String,String> params,Map<String,String> files, MyNetListener callback)

你說(shuō)還有很常見(jiàn)的拉取網(wǎng)絡(luò)圖片并顯示在imageview中?
那就是圖片加載框架的事兒了,不應(yīng)該交給網(wǎng)絡(luò)框架處理.推薦fresco,以及我的這個(gè)FrescoUtils.

以上api的思維導(dǎo)圖概覽

基本api.jpg

返回的數(shù)據(jù):統(tǒng)一的回調(diào)

回調(diào)采用抽象類的形式,而不是接口的形式

public void onPreExecute() {}//統(tǒng)一的開始
public void onFinish(){}//統(tǒng)一的結(jié)束

public  void onEmpty(){}//內(nèi)容為空時(shí)--一般用在返回空的jsonArray時(shí)([]).


//成功的幾種情況:
public abstract void onSuccess(T response,String resonseStr);//主回調(diào)

public  void onSuccessArr(List<T> response,String resonseStr){}//主回調(diào),需要時(shí)復(fù)寫

public  void onSuccessObj(T response,String responseStr,String data,int code,String msg){
        onSuccess(response,responseStr);
}

public  void onSuccessArr(List<T> response, String responseStr, String data, int code, String msg){
    onSuccessArr(response,responseStr);
}

//失敗的回調(diào)

public void onError(String msgCanShow) {}//主回調(diào)

 public void onUnFound() {
    onError("沒(méi)有找到該內(nèi)容");
}
public    void onUnlogin(){
    onError("您還沒(méi)有登錄");
}


 public void onCodeError(String msgCanShow,String hiddenMsg,int code) {
    if (TextUtils.isEmpty(msgCanShow)){
        onError("錯(cuò)誤碼為:"+code);
    }else {
        onError(msgCanShow);
    }
}

//進(jìn)度回調(diào)
public void onProgressChange(long fileSize, long downloadedSize) {}

自定義請(qǐng)求時(shí)的一些參數(shù)

沒(méi)什么好說(shuō)的,直接看圖,清晰明了

自定義設(shè)置的api.jpg

一個(gè)請(qǐng)求示例

            Map map8 = new HashMap<>();
            map8.put("versionName","1.0.0");
            map8.put("appType",0);
            MyNetApi.postStandardJson("http://app.xxtt.com:9090/app/appVersion/getLatestVersion",
                    map8, VersionInfo.class, new MyNetListener<VersionInfo>() {
                        @Override
                        public void onSuccess(VersionInfo response, String resonseStr) {
                            Logger.e(resonseStr);
                        }

                        @Override
                        public void onError(String msgCanShow) {
                            super.onError(msgCanShow);
                            Logger.e(msgCanShow);
                        }
                    })
                    .setParamsAsJson()
                    .setIsAppendToken(false)
                    .setCustomCodeValue(1,2,3)
                    .start();

代碼

https://github.com/hss01248/NetWrapper

附圖:整體層次圖

ps.是的,我沒(méi)有用逼格比較高的Rxjava,主要是因?yàn)楸容^習(xí)慣回調(diào)模式,這種模式下,代碼的聚合度比較高.

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末邑跪,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子畔况,更是在濱河造成了極大的恐慌茵瀑,老刑警劉巖砰奕,帶你破解...
    沈念sama閱讀 218,546評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件橡娄,死亡現(xiàn)場(chǎng)離奇詭異坯认,居然都是意外死亡卷中,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,224評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門唬格,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)家破,“玉大人颜说,你說(shuō)我怎么就攤上這事购岗。” “怎么了门粪?”我有些...
    開封第一講書人閱讀 164,911評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵喊积,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我玄妈,道長(zhǎng)乾吻,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,737評(píng)論 1 294
  • 正文 為了忘掉前任拟蜻,我火速辦了婚禮绎签,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘酝锅。我一直安慰自己诡必,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,753評(píng)論 6 392
  • 文/花漫 我一把揭開白布搔扁。 她就那樣靜靜地躺著爸舒,像睡著了一般。 火紅的嫁衣襯著肌膚如雪稿蹲。 梳的紋絲不亂的頭發(fā)上扭勉,一...
    開封第一講書人閱讀 51,598評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音苛聘,去河邊找鬼涂炎。 笑死,一個(gè)胖子當(dāng)著我的面吹牛设哗,可吹牛的內(nèi)容都是我干的唱捣。 我是一名探鬼主播,決...
    沈念sama閱讀 40,338評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼熬拒,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼爷光!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起澎粟,我...
    開封第一講書人閱讀 39,249評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤蛀序,失蹤者是張志新(化名)和其女友劉穎欢瞪,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體徐裸,經(jīng)...
    沈念sama閱讀 45,696評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡遣鼓,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,888評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了重贺。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片骑祟。...
    茶點(diǎn)故事閱讀 40,013評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖气笙,靈堂內(nèi)的尸體忽然破棺而出次企,到底是詐尸還是另有隱情,我是刑警寧澤潜圃,帶...
    沈念sama閱讀 35,731評(píng)論 5 346
  • 正文 年R本政府宣布缸棵,位于F島的核電站,受9級(jí)特大地震影響谭期,放射性物質(zhì)發(fā)生泄漏堵第。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,348評(píng)論 3 330
  • 文/蒙蒙 一隧出、第九天 我趴在偏房一處隱蔽的房頂上張望踏志。 院中可真熱鬧,春花似錦胀瞪、人聲如沸针余。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,929評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)涵紊。三九已至,卻和暖如春幔摸,著一層夾襖步出監(jiān)牢的瞬間摸柄,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,048評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工既忆, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留驱负,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,203評(píng)論 3 370
  • 正文 我出身青樓患雇,卻偏偏與公主長(zhǎng)得像跃脊,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子苛吱,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,960評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容

  • AFHTTPRequestOperationManager 網(wǎng)絡(luò)傳輸協(xié)議UDP酪术、TCP、Http、Socket绘雁、X...
    Carden閱讀 4,338評(píng)論 0 12
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見(jiàn)模式的工具(例如配置管理橡疼,服務(wù)發(fā)現(xiàn),斷路器庐舟,智...
    卡卡羅2017閱讀 134,657評(píng)論 18 139
  • 點(diǎn)擊查看原文 Web SDK 開發(fā)手冊(cè) SDK 概述 網(wǎng)易云信 SDK 為 Web 應(yīng)用提供一個(gè)完善的 IM 系統(tǒng)...
    layjoy閱讀 13,766評(píng)論 0 15
  • 國(guó)家電網(wǎng)公司企業(yè)標(biāo)準(zhǔn)(Q/GDW)- 面向?qū)ο蟮挠秒娦畔?shù)據(jù)交換協(xié)議 - 報(bào)批稿:20170802 前言: 排版 ...
    庭說(shuō)閱讀 10,974評(píng)論 6 13
  • 今天中午陪孩子們一起看《龍貓》,感受什么是“富強(qiáng)杠娱、民主挽牢、和諧”。當(dāng)看到小梅得知媽媽的病情惡化便抱著玉米棒向連大人都...
    枧文閱讀 354評(píng)論 0 0