是時候用 NoHttp 來替換 Volley 了


NoHttp一個有情懷的框架

我們日常生活中常用的App,包括我們開發者平常的開發中,有90%以上的App都用了Http來和服務器做交互。隨着Android6.0開始AndroidSDK中刪除了HttpClient的相關的API,我們有必要選擇一個可以兼容高低版本系統的Http框架,Google的官方文檔中推薦我們使用HttpURLConnection,但是鑒於HttpURLConnection的API過於簡單,並且在高低版本系統中有不同的bug,因此開發者如果使用HttpURLConnection封裝的話,復雜度和工作量都不少,這就是NoHttp產生的背景。

NoHttp之所以叫NoHttp,是因為我們使用NoHttp的時候不用管Http協議的東西,NoHttp底層都自動完成了判斷,開發者只需要直接調用就好。NoHttp支持傻瓜式調用,支持高級擴展,是一個從小白到大牛都可以使用的Android Http框架。

NoHttp的底層使用了HttpURLConnection來封裝,有人推薦用OkHttp來封裝,其實OkHttp對HttpClient和HttpURLConnection都提供了接口,從Android4.4開始HttpURLConnection的底層就是用OkHttp來實現的,現在手機大多數都是4.4以上了吧,尤其國外的更新的更快,其次也沒有必要再引進okhttp和okio(okhttp依賴okio)來增大apk的體積。

NoHttp相關鏈接

NoHttp文檔: http://doc.nohttp.net

NoHttp官網: http://www.nohttp.net

NoHttp源碼: https://github.com/yanzhenjie/NoHttp

NoHttp簡介

NoHttp是一個Android開源網絡框架,實現了RFC2616(Http1.1)協議,一個標准的Http框架。支持普通請求、文件的上傳與下載、自動維持Cookie、支持RFC2616規定的所有請求方法(POST、GET、HEAD……)、支持Https(包括訪問自簽名網站)、支持請求優先級、支持請求與Activity聯動、提供了五種緩存策略供開發者選擇……

  • 請求和下載都是隊列,平均分配每個線程的資源,支持多個請求並發。
  • 支持GET、POST、PUT、PATCH、HEAD、DELETE、OPTIONS、TRACE等請求協議。
  • 支持基於POST、PUT、PATCH、DELETE的文件上傳(Html表單原理)。
  • 文件下載、上傳下載、上傳和下載的狀態回調、錯誤回調。
  • 提供了五種數據緩存策略供開發者選擇使用。
  • 支持自定義Request,利用NoHttp泛型可以解析成任何數據格式(String、Json、JavaBean等)。
  • 支持Session、Cookie的自動維持,App重啟、關開機后還持續維持。
  • 支持Https、自簽名網站Https的訪問、支持Https雙向驗證。
  • 支持取消某個請求、取消指定多個請求、取消所有請求。
  • 支持重定向、多級別重定向。支持代理、支持Request的優先級。

使用方法

  • Eclipse使用Jar包,如果需要依賴源碼,請自行下載。

  • AndroidStudio使用Gradle構建添加依賴(推薦)

compile'com.yolanda.nohttp:nohttp:1.0.2'

友好的調試模式

NoHttp提供了調試模式,打開后可以清晰的看到請求過程、怎么傳遞數據等,基本不用抓包。可以看到請求頭、請求數據、響應頭、Cookie等的過程。你也不用擔心Log太多會讓你眼花繚亂,想象不到的整潔。

請求

  • 支持請求String、Json、FastJson、Gson、Bitmap、JavaBean、XML等擴展。
  • 異步請求,拿到結果直接更新UI,支持同步請求。

多文件上傳

所有下載均有進度回調、錯誤回調等友好的接口。

  • 大文件上傳,不會發生OOM。
  • 多文件上傳,多個key多個文件,一個key多個文件( List<File> )。
  • 支持File、InputStream、ByteArray、Bitmap,實現NoHttp的Binary接口,理論上任何東西都可以傳。
  • 支持取消上傳。

文件下載

  • 文件下載,支持多個文件同時下載,並且有進度回調、錯誤回調等。
  • 支持暫停繼續下載,支持取消下載,支持斷點續傳。
  • 利用NoHttp的多文件下載可以做一個下載管理器。

緩存模式

  • 僅僅請求網絡。
  • 僅僅讀取緩存。
  • 標准Http協議緩存(比如響應碼是304的情況),需要服務器支持,如果服務器不支持就和普通請求一樣。
  • 先請求網絡,請求失敗后返回緩存。
  • 先讀取緩存,緩存不存在再請求網絡。

取消請求

所有取消都支持正在執行的請求。

  • 支持取消某個請求。
  • 支持取消用sign指定的幾個請求。
  • 支持取消所有的請求。

請求自動維持Cookie

  • 支持Session、Cookie、臨時Cookie的位置。
  • 支持App重啟、關機開機后繼續持久化維持。
  • 提供了接口,允許開發者監聽Cookie的變化,也可以改變某個Cookie的值。

重定向

  • 對於Http301、302、303、307等重定向的支持。
  • 支持多級重定向嵌套。
  • 支持禁用重定向、NoHttp提供了操作重定向的接口。

代理

  • 標准的Java的Api,ProXy:指定代理的IP和Port。
  • 比如調試時代理到自己電腦進行抓包,比如用代理訪問Google。

一. 請求

String請求

// String 請求對象
Request<String>request= NoHttp.createStringRequest(url,requestMethod); 

Json請求

// JsonObject
Request<JSONObject>request= NoHttp.createJsonObjectRequest(url,reqeustMethod); ... // JsonArray Request<JSONArray>request= NoHttp.createJsonArrayRequest(url,reqeustMethod); 

Bitmap請求

Request<Bitmap>request= NoHttp.createImageRequest(url,requestMethod); 

添加參數

Request<JSONObject>request= ...
request.add("name", "yoldada");// String類型 request.add("age", 18);// int類型 request.add("sex", '0')// char類型 request.add("time", 16346468473154); // long類型 ... 

添加到隊列

RequestQueuerequestQueue= NoHttp.newRequestQueue();
// 或者傳一個並發值,允許三個請求同時並發
// RequestQueue requestQueue = NoHttp.newRequestQueue(3); // 發起請求 requestQueue.add(what,request,responseListener); 

上面添加到隊列時有一個what,這個what會在 responseLisetener 響應時回調給開發者,所以我們可以用一個 responseLisetener 接受多個請求的響應,用what來區分結果。而不用像有的框架一樣,每一個請求都要new一個回調。

同步請求

在當前線程發起請求,在線程這么使用。

Request<String>request= ... Response<String>response= NoHttp.startRequestSync(request); if (response.isSucceed()) { // 請求成功 } else { // 請求失敗 } 

二. 文件上傳

支持多文件上傳,多個key多個文件,一個key多個文件( List<File> )。支持File、InputStream、ByteArray、Bitmap,實現NoHttp的Binary接口,理論上任何東西都可以傳。

單個文件

Request<String>request= ... request.add("file", new FileBinary(file)); 

上傳多個文件、多個Key多個文件形式

這里可以添加各種形式的文件,File、Bitmap、InputStream、ByteArray:

Request<String>request= ...
request.add("file1", new FileBinary(File)); request.add("file2", new FileBinary(File)); request.add("file3", new InputStreamBinary(InputStream)); request.add("file4", new ByteArrayBinary(byte[])); request.add("file5", new BitmapStreamBinary(Bitmap)); 

上傳多個文件、一個Key多個文件形式

用同一個key添加,如果請求方法是POST、PUT、PATCH、DELETE,同一個key不會被覆蓋。

Request<String>request= ...
fileList.add("image", new FileBinary(File)); fileList.add("image", new InputStreamBinary(InputStream)); fileList.add("image", new ByteArrayBinary(byte[])); fileList.add("image", new BitmapStreamBinary(Bitmap)); 

或者:

Request<String>request= ... List<Binary>fileList= ... fileList.add(new FileBinary(File)); fileList.add(new InputStreamBinary(InputStream)); fileList.add(new ByteArrayBinary(byte[])); fileList.add(new BitmapStreamBinary(Bitmap)); request.add("file_list",fileList); 

三. 下載文件

因為下載文件代碼比較多,這里貼關鍵部分,具體的請參考sample。

發起下載請求

//下載文件
downloadRequest= NoHttp.createDownloadRequest...
// what 區分下載 // downloadRequest 下載請求對象 // downloadListener 下載監聽 downloadQueue.add(0,downloadRequest,downloadListener); 

暫停或者停止下載

downloadRequest.cancel();

監聽下載過程

private DownloadListenerdownloadListener= new DownloadListener() { @Override public voidonStart(intwhat, booleanresume, longpreLenght, Headersheader, longcount) { // 下載開始 } @Override public voidonProgress(intwhat, intprogress, longdownCount) { // 更新下載進度 } @Override public voidonFinish(intwhat, StringfilePath) { // 下載完成 } @Override public voidonDownloadError(intwhat, StatusCodecode, CharSequencemessage) { // 下載發生錯誤 } @Override public voidonCancel(intwhat) { // 下載被取消或者暫停 } }; 

四. 緩存模式

1. Http標准協議的緩存,比如響應碼是304時

NoHttp本身是實現了RFC2616,所以這里不用設置或者設置為DEFAULT。

Request<JSONObject>request= NoHttp.createJsonObjectRequest(url); request.setCacheMode(CacheMode.DEFAULT); 

2. 當請求服務器失敗的時候,讀取緩存

請求服務器成功則返回服務器數據,如果請求服務器失敗,讀取緩存數據返回。

Request<JSONObject>request= NoHttp.createJsonObjectRequest(url); request.setCacheMode(CacheMode.REQUEST_NETWORK_FAILED_READ_CACHE); 

3. 如果發現有緩存直接成功,沒有緩存才請求服務器

我們知道ImageLoader的核心除了內存優化外,剩下一個就是發現把內地有圖片則直接使用,沒有則請求服務器,所以NoHttp這一點非常使用做一個ImageLoader。如果沒有緩存才去請求服務器,否則使用緩存:

Request<JSONObject>request= NoHttp.createJsonObjectRequest(url); // 非標准Http協議,改變緩存模式為IF_NONE_CACHE_REQUEST_NETWORK request.setCacheMode(CacheMode.IF_NONE_CACHE_REQUEST_NETWORK); 

請求圖片,緩存圖片:

Request<Bitmap>request= NoHttp.createImageRequest(imageUrl); request.setCacheMode(CacheMode.IF_NONE_CACHE_REQUEST_NETWORK); 

4. 僅僅請求網絡

這里不會讀取緩存,也不會使用Http304:

Request<Bitmap>request= NoHttp.createImageRequest(imageUrl); request.setCacheMode(CacheMode.ONLY_REQUEST_NETWORK); ... 

5. 僅僅讀取緩存

如果沒有緩存才去請求服務器,否則使用緩存,緩存圖片演示:

Request<Bitmap>request= NoHttp.createImageRequest(imageUrl); request.setCacheMode(CacheMode.ONLY_READ_CACHE); 

五. 取消請求

取消單個請求

直接調用請求對象的cancel方法。

request.cancel();

從隊列中取消指定的請求

給請求set一個sign,取消的時候調用隊列的cancelBySign就可以取消掉所有指定這個sign的請求。

request.setCancelSign(sign);
...
queue.cancelBySign(sign);

取消隊列中所有請求

queue.cancelAll();

停止隊列

隊列停止后再添加請求到隊列后,請求不會被執行。

RequestQueuequeue= NoHttp.newRequestQueue();
...
queue.stop();

六. 自定義請求類型: FastJsonRequest

定義請求對象

public class FastJsonRequest extends RestRequestor<JSONObject> { public FastJsonRequest(Stringurl) { super(url); } public FastJsonRequest(Stringurl, RequestMethodrequestMethod) { super(url,requestMethod); } @Override public JSONObjectparseResponse(Stringurl, Headersheaders, byte[]responseBody) { Stringresult= StringRequest.parseResponseString(url,headers,responseBody); JSONObjectjsonObject= null; if (!TextUtils.isEmpty(result)) { jsonObject=JSON.parseObject(result); } else { // 這里默認的錯誤可以定義為你們自己的數據格式 jsonObject=JSON.toJSON("{}"); } returnjsonObject; } @Override public StringgetAccept() { // 告訴服務器你接受什么類型的數據 return "application/json"; } } 

b. 使用自定義請求-和NoHttp默認請求沒有區別的哦

Request<JSONObject>mRequest= new FastJsonRequest(url,requestMethod); queue.add(what,mRequest,responseListener); 

七. 混淆

需要知道的

NoHttp全部的類都可以混淆。

NoHttp1.0.0使用了leve23的api,所以打包的時候要用leve23才行。

NoHttp1.0.1使用了反射調用了高級或者低級的api,所以只要是leve9以上的sdk都可以編譯。

NoHttp1.0.2同NoHttp1.0.1一樣,在NoHttp1.0.1的基礎上進行了優化和bug修復。是目前功能最全,最穩定的一個版本,暫時未發現bug。

如果你非要keep

-dontwarn com.yolanda.nohttp.**
-keep class com.yolanda.nohttp.**{*;} 

權限

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM