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" />