app的架構,不論是MVC,MVP,MVVM,架構演變中,貫穿始終的概念都是分層和解耦.那麼這個分層和解耦怎麼體現出來?
簡單地說就是,我這一層接收上一層的輸入,上一層的你別管我怎麼處理,我最終會給你一個輸出/返回值,你徹底不用理會我是怎麼處理的,只要有輸入,就會有輸出,並且通常是經過一個簡單的方法的調用來實現.java
咱們的口號是:一行代碼完成網絡請求!git
其實很是簡單,看接口文檔你就知道了怎麼作了:就傳那些個參數,返回就是那個json之類的.把接口文檔轉化爲咱們調用的一個方法,這網絡層與上層的接口就能夠說是設計好了.github
接口文檔寫了什麼:(百度圖片隨便找的一個)json
因此,咱們網絡層應該封裝成這樣一個方法:api
請求方式,url路徑,請求的參數key和值
注: 對於多個POST請求參數key-value,有的接口會定義成Map形式,有的會定義成Json形式.其實本質上都是同樣的,都是在requestBody上POST一個字符串(字符流)出去,只不過前者的形式是a=4&t=5的形式,然後者是一個json形式.
整體上來說,仍是前者比較多見,畢竟參數拼接形式與GET請求一致,服務器端處理比較方便.服務器
對於返回字符流數據的狀況,能夠概括爲返回一個String對象,怎麼處理就看具體狀況了.網絡
app中常見的是返回json格式的字符串.固然,通常app裏須要的是解析好的javabean,那麼網絡框架接口應該能直接返回一個解析好的javabean.多線程
固然,更進一步來看,大多數規範的api(看看各大api市場,好比聚合api之類的)返回的json格式都具有如下特色:架構
通常爲三個字段,分別表示狀態碼,相關提示信息,以及一個用於攜帶數據的字段.(好比:{"code":0,"msg":"登陸成功","data":{...}}).攜帶數據的字段能夠攜帶任何類型的數據,null,數字,字符串,jsonObject,JsonArray均可以.app
在這裏,我把這種三個字段的json稱爲"標準格式的json"
getString(String url, Map map, MyNetListener listener)//get請求,返回一個string,拿到這個string postString( String url, Map map, MyNetListener listener) getCommonJson(String url, Map map, Class clazz, MyNetListener listener)//get請求,返回一個json,將整個json解析成javabean postCommonJson(String url, Map map, Class clazz, MyNetListener listener) getStandardJson(String url, Map map, Class clazz, MyNetListener listener)//get請求,返回一個標準格式的json postStandardJson(String url, Map map, Class clazz, MyNetListener listener) //post請求,返回一個標準格式的json,經過傳入的clazz,直接解析返回data字段的javabean //若是參數以json形式發出,那麼再調用方法setParamsAsJson()便可.
通常是GET請求,傳入url.請求參數無關緊要.最終下載獲得一個文件(路徑可預先指定),而且在下載的過程當中有進度的回調.
注意: 我上面一層不須要知道你的什麼網絡流啊,斷點下載啊,分片多線程下載之類的細節.
download(String url, String savedpath, MyNetListener callback)
POST請求,傳入url,請求參數,文件相關的key名,文件的地址,最終返回一個結果(成功或失敗),而且在上傳的過程當中有進度回調.
一樣的,上一層不須要知道里面具體的header設置啊,斷點續傳啊,分片上傳之類的細節.
注意: http是支持多文件上傳的.
upLoad(String url, Map<String,String> params,Map<String,String> files, MyNetListener callback)
你說還有很常見的拉取網絡圖片並顯示在imageview中?
那就是圖片加載框架的事兒了,不該該交給網絡框架處理.推薦fresco,以及個人這個FrescoUtils.
回調採用抽象類的形式,而不是接口的形式
public void onPreExecute() {}//統一的開始 public void onFinish(){}//統一的結束 public void onEmpty(){}//內容爲空時--通常用在返回空的jsonArray時([]). //成功的幾種狀況: public abstract void onSuccess(T response,String resonseStr);//主回調 public void onSuccessArr(List<T> response,String resonseStr){}//主回調,須要時複寫 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); } //失敗的回調 public void onError(String msgCanShow) {}//主回調 public void onUnFound() { onError("沒有找到該內容"); } public void onUnlogin(){ onError("您尚未登陸"); } public void onCodeError(String msgCanShow,String hiddenMsg,int code) { if (TextUtils.isEmpty(msgCanShow)){ onError("錯誤碼爲:"+code); }else { onError(msgCanShow); } } //進度回調 public void onProgressChange(long fileSize, long downloadedSize) {}
沒什麼好說的,直接看圖,清晰明瞭
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.是的,我沒有用逼格比較高的Rxjava,主要是由於比較習慣回調模式,這種模式下,代碼的聚合度比較高.