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構建添加依賴(推薦)
1
|
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請求
1
2
|
//
String 請求對象 Request<String>
request = NoHttp.createStringRequest(url, requestMethod); |
Json請求
1
2
3
4
5
|
//
JsonObject Request<JSONObject>
request = NoHttp.createJsonObjectRequest(url, reqeustMethod); ... //
JsonArray Request<JSONArray>
request = NoHttp.createJsonArrayRequest(url, reqeustMethod); |
Bitmap請求
1
|
Request<Bitmap>
request = NoHttp.createImageRequest(url, requestMethod); |
添加參數
1
2
3
4
5
6
|
Request<JSONObject>
request = ... request.add( "name" , "yoldada" ); //
String類型 request.add( "age" , 18 ); //
int類型 request.add( "sex" , '0' ) //
char類型 request.add( "time" , 16346468473154 ); //
long類型 ... |
添加到隊列
1
2
3
4
5
6
|
RequestQueue
requestQueue = NoHttp.newRequestQueue(); //
或者傳一個併發值,允許三個請求同時併發 //
RequestQueue requestQueue = NoHttp.newRequestQueue(3); //
發起請求 requestQueue.add(what,
request, responseListener); |
上面添加到隊列時有一個what,這個what會在responseLisetener
響應時回調給開發者,所以我們可以用一個responseLisetener
接受多個請求的響應,用what來區分結果。而不用像有的框架一樣,每一個請求都要new一個回調。
同步請求
在當前線程發起請求,在線程這麼使用。
1
2
3
4
5
6
7
|
Request<String>
request = ... Response<String>
response = NoHttp.startRequestSync(request); if
(response.isSucceed()) { //
請求成功 } else
{ //
請求失敗 } |
二. 文件上傳
支持多文件上傳,多個key多個文件,一個key多個文件(List<File>
)。支持File、InputStream、ByteArray、Bitmap,實現NoHttp的Binary接口,理論上任何東西都可以傳。
單個文件
1
2
|
Request<String>
request = ... request.add( "file" , new
FileBinary(file)); |
上傳多個文件、多個Key多個文件形式
這裏可以添加各種形式的文件,File、Bitmap、InputStream、ByteArray:
1
2
3
4
5
6
|
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不會被覆蓋。
1
2
3
4
5
|
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)); |
或者:
1
2
3
4
5
6
7
|
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。
發起下載請求
1
2
3
4
5
6
|
//下載文件 downloadRequest
= NoHttp.createDownloadRequest... //
what 區分下載 //
downloadRequest 下載請求對象 //
downloadListener 下載監聽 downloadQueue.add( 0 ,
downloadRequest, downloadListener); |
暫停或者停止下載
1
|
downloadRequest.cancel(); |
監聽下載過程
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
private
DownloadListener downloadListener = new
DownloadListener() { @Override public
void
onStart( int
what, boolean
resume, long
preLenght, Headers header, long
count) { //
下載開始 } @Override public
void
onProgress( int
what, int
progress, long
downCount) { //
更新下載進度 } @Override public
void
onFinish( int
what, String filePath) { //
下載完成 } @Override public
void
onDownloadError( int
what, StatusCode code, CharSequence message) { //
下載發生錯誤 } @Override public
void
onCancel( int
what) { //
下載被取消或者暫停 } }; |
四. 緩存模式
1. Http標準協議的緩存,比如響應碼是304時
NoHttp本身是實現了RFC2616,所以這裏不用設置或者設置爲DEFAULT。
1
2
|
Request<JSONObject>
request = NoHttp.createJsonObjectRequest(url); request.setCacheMode(CacheMode.DEFAULT); |
2. 當請求服務器失敗的時候,讀取緩存
請求服務器成功則返回服務器數據,如果請求服務器失敗,讀取緩存數據返回。
1
2
|
Request<JSONObject>
request = NoHttp.createJsonObjectRequest(url); request.setCacheMode(CacheMode.REQUEST_NETWORK_FAILED_READ_CACHE); |
3. 如果發現有緩存直接成功,沒有緩存才請求服務器
我們知道ImageLoader的核心除了內存優化外,剩下一個就是發現把內地有圖片則直接使用,沒有則請求服務器,所以NoHttp這一點非常使用做一個ImageLoader。
如果沒有緩存纔去請求服務器,否則使用緩存:
1
2
3
|
Request<JSONObject>
request = NoHttp.createJsonObjectRequest(url); //
非標準Http協議,改變緩存模式爲IF_NONE_CACHE_REQUEST_NETWORK request.setCacheMode(CacheMode.IF_NONE_CACHE_REQUEST_NETWORK); |
請求圖片,緩存圖片:
1
2
|
Request<Bitmap>
request = NoHttp.createImageRequest(imageUrl); request.setCacheMode(CacheMode.IF_NONE_CACHE_REQUEST_NETWORK); |
4. 僅僅請求網絡
這裏不會讀取緩存,也不會使用Http304:
1
2
3
|
Request<Bitmap>
request = NoHttp.createImageRequest(imageUrl); request.setCacheMode(CacheMode.ONLY_REQUEST_NETWORK); ... |
5. 僅僅讀取緩存
如果沒有緩存纔去請求服務器,否則使用緩存,緩存圖片演示:
1
2
|
Request<Bitmap>
request = NoHttp.createImageRequest(imageUrl); request.setCacheMode(CacheMode.ONLY_READ_CACHE); |
五. 取消請求
取消單個請求
直接調用請求對象的cancel方法。
1
|
request.cancel(); |
從隊列中取消指定的請求
給請求set一個sign,取消的時候調用隊列的cancelBySign就可以取消掉所有指定這個sign的請求。
1
2
3
|
request.setCancelSign(sign); ... queue.cancelBySign(sign); |
取消隊列中所有請求
1
|
queue.cancelAll(); |
停止隊列
隊列停止後再添加請求到隊列後,請求不會被執行。
1
2
3
|
RequestQueue
queue = NoHttp.newRequestQueue(); ... queue.stop(); |
六. 自定義請求類型: FastJsonRequest
定義請求對象
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
public
class
FastJsonRequest extends
RestRequestor<JSONObject> { public
FastJsonRequest(String url) { super (url); } public
FastJsonRequest(String url, RequestMethod requestMethod) { super (url,
requestMethod); } @Override public
JSONObject parseResponse(String url, Headers headers, byte []
responseBody) { String
result = StringRequest.parseResponseString(url, headers, responseBody); JSONObject
jsonObject = null ; if
(!TextUtils.isEmpty(result)) { jsonObject
= JSON.parseObject(result); } else
{ //
這裏默認的錯誤可以定義爲你們自己的數據格式 jsonObject
= JSON.toJSON( "{}" ); } return
jsonObject; } @Override public
String getAccept() { //
告訴服務器你接受什麼類型的數據 return
"application/json" ; } } |
b. 使用自定義請求-和NoHttp默認請求沒有區別的哦
1
2
|
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
1
2
|
-dontwarn
com.yolanda.nohttp.** -keep class
com.yolanda.nohttp.**{*;} |
權限
1
2
3
4
5
|
< 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"
/> |