HTTP 請求和 Json 解析幾乎是當前 APP 開發必備技能了,而 OkHttp 框架又是 Android 開發最經常使用的網絡請求框架之一,所以我基於它進行了二次封裝,旨在更高效、快速的完成 APP 應用程序網絡請求功能的構建。git
爲何要進行二次封裝?瞭解過 OkHttp 的應該知道,要建立一個 OkHttp 請求的過程有些繁瑣,第一你得建立一個 OkHttpClient,額外的你得建立一個請求 Request,其次每次還得作一大堆配置,十分繁瑣。github
關於 Json,目前最好的兩個框架分別是 org.json 和 Gson,二者各有長處,而 org.json 存在的最大的麻煩在於其解析或構建 Json 都須要 捕獲異常,而即使是 Gson,對於空數據的狀況依然也會一籌莫展。json
基於快速開發以及防後端撕逼原則,對於 Json 解析咱們是須要一些寬容度的,即:即使 Json 可能不完整,可能有問題,也不能讓咱們的 App 崩(bei)潰(guo),基於上述原則,那麼咱們的封裝目的也就很明確了,那就是一方面要將網絡請求這事情變簡單,另外一方面就是讓 Json 解析更爲容易。後端
這個框架就是對於上述問題解決思路的封裝結果了,先上 GitHub 地址: github.com/kongzue/Bas…bash
通常而言,對於的代碼編寫方式分爲一鍵構建法和流式構建法,而 BaseOkHttpV3 二者都支持,習慣怎麼用均可以:服務器
//一鍵構建法:
HttpRequest.POST(context, "http://www.example.com/femaleNameApi", new Parameter().add("page", "1"), new ResponseListener() {
@Override
public void onResponse(String response, Exception error) {
//返回數據 response
}
});
//流式寫法:
HttpRequest.build(context, "http://www.example.com/femaleNameApi")
.addHeaders("Charset", "UTF-8")
.addParameter("page", "1")
.addParameter("token", "A128")
.setResponseListener(new ResponseListener() {
@Override
public void onResponse(String response, Exception error) {
//返回數據 response
}
})
.doPost();
複製代碼
接下來講說請求成功和異常的處理,在 OkHttp 框架中,請求返回結果成功與失敗是分別放在不一樣的方法中執行的,且須要建立 Call 對象才能處理:網絡
Call call = okHttpClient.newCall(request);
call.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
//請求失敗
}
@Override
public void onResponse(Call call, Response response) throws IOException {
//請求成功,注意這裏還有個坑,response.body().string() 只能獲取一次
}
});
複製代碼
但咱們常用場景中,須要在請求開始時彈出一個 ProgressDialog(加載中提示框)來阻斷用戶重複請求的行爲,而不管請求成功仍是失敗,這個對話框都須要被關閉(dismiss)那麼問題來了,按照 OkHttp 框架原先的寫法,你須要在 onFailure 和 onResponse 兩個方法中都執行 progressDialog.dismiss(); 代碼重複,利用率低。框架
在上述 BaseOkHttpV3 框架中,僅在同一個 onResponse 方法中返回,開發者只須要作判斷便可,error 和 response 同時只會有一個是 null,而 error == null 時即爲請求成功,這樣不管請求成功與失敗都須要執行的代碼就能夠只寫一次了。異步
一般咱們在同一個程序中構建大多數請求都是使用同一個域名地址的子接口地址的,那麼可否減輕這塊的代碼重複量?即,配置全局請求地址。BaseOkHttpV3 框架中也有考慮這種問題,在 BaseOkHttpV3 中提供了大量的全局配置方法,例如全局服務器地址 BaseOkHttp.serviceUrl,配製後全部請求編寫時,僅須要寫子接口部分的地址便可,框架會自動使用 BaseOkHttp.serviceUrl + 當前建立的請求 url 進行組合發送請求,要臨時取消這種組合單獨請求別的服務接口地址,僅須要在建立請求時傳入「http」開頭的請求 url 便可自動不帶全局服務器地址發送請求。ide
諸如此類的全局配置還有不少,例如全局 Header 請求頭、全局參數、全局參數攔截器、全局返回攔截器等等,這都是爲了方便更多請求場景須要且簡化開發成本所作的功能,具體請參考 Github 文檔。
最後,BaseOkHttpV3 返回請求結果時,區別於 OkHttp,默認是在主線程返回的,以方便直接對佈局進行操做,如需異步線程請手動自行建立。
Json 是目前最經常使用的數據封裝方式了,區別於以往的 XML,它更加輕便簡潔,其實 org.json 和 Gson 對他的處理已經至關完善了,但我依然以爲有更進一步的空間。
對於 Json 的解析,BaseOkHttpV3 提供了JsonUtil 工具類來完成,JsonUtil 工具類是基於 org.json 庫的二次封裝,但 JsonUtil 的輸出不是 JsonObject 或 JsonArray 對象,而是基於 Map 和 List 的 JsonMap 和 JsonList 對象,且提供了獨立的 get 方法,以保證讀取到的數據不會出現空指針異常。
JsonMap 和 JsonList 的優點主要在於其解析方便,不須要捕獲異常處理,且徹底不會空指針。對於異常的 json 文本,例如如下文本:
{
"name":"abc",
"age":"",
"data":null
}
複製代碼
其中的 age 預期是 int 類型,若是使用 org.json 和 Gson 庫,均可能遇到麻煩,但對於 BaseOkHttpV3 來講是毫無問題的,使用 getInt("age") 獲取到的值會是 0,若是你想作判斷,能夠設置默認值爲 -1,使用代碼 getInt("age", -1) 便可,在 BaseOkHttpV3 的 Json 解析框架中,全部獲取到的值,不管 getString(key)、getInt(key)、getBoolean(key)仍是其餘類型,甚至對於上述使用 Json,使用 getJsonMap("data").getString("message"); 的代碼,都不會出現空指針,能夠儘管放心大膽的解析。
如此設計的主要目的是爲了方便解決對於可能出現的後端給出數據存在異常的狀況下,保證 App 不崩潰,且可以高效構建代碼。在 BaseOkHttpV3 的 Json 解析庫中,你甚至能夠忽略類型,對於 boolean 的值能夠直接解析成 string,對於 string 的值你也能夠直接解析成 int,都不會出現 App 的問題,儘管這確實有些不嚴謹,但卻能大大提高開發的效率,縮短開發週期,減小沒必要要的麻煩。
另外, JsonMap 和 JsonList 對象是 Map 和 List 的子類,也就是說,對於一段 Json 集合,能夠直接經過 JsonUtil 解析成 JsonList 參與 ListView、RecycleView 等組件的適配器 Adapter 構建,快速完成從網絡請求數據到界面呈現的轉換,省去構造 JavaBean 的繁瑣步驟。
BaseOkHttpV3 還有一個很是亮點的設計,那就是日誌打印,這個設計也主要是爲了防止出現責任不明的問題,對於 BaseOkHttpV3 的請求,在開啓日誌打印開關後 BaseOkHttp.DEBUGMODE = true; 你能夠在控制檯看到很是完整規範的日誌結果:
對於 Json 文本會自動進行格式化,且針對每個接口的發送、返回、錯誤都有明確的顯示,我相信這對於平常開發查錯來講也會是極佳的助力。
BaseOkHttpV3 的封裝主要是爲了解決開發過程當中遇到的不少痛點和難點,本文着重講述了 BaseOkHttpV3 的封裝目的以及對於通常請求以及 Json 解析的良好支持,除此以外,BaseOkHttpV3 也對 PUT、GET、DELETE 請求、HTTPS、WebSocket 以及 Cookie 作了封裝,有興趣能夠移駕 Github 詳細查看:github.com/kongzue/Bas…
若有任何疑問能夠在 Github 提出您的 issues。寫文章不易,若是以爲好還勞煩點個贊吧!