是時候用NoHttp來替換Volley了

NoHttp一個有情懷的框架

NoHttpLogo

我們日常生活中常用的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包,如果需要依賴源碼,請自行下載。

    下載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" />
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章