Http標准協議Android網絡框架——NoHttp


  1. NoHttp詳細文檔:http://doc.nohttp.net

  2. NoHttp公益測試接口:http://api.nohttp.net

支持與RxJava完美結合、支持一句話切換底層為OkHttp,支持緩存數據到數據庫或SD卡和數據庫,並對數據做了加密保護,支持請求Restful風格的接口,比Retrofit更簡單易用。

歡迎加入QQ技術交流群:46523908


效果預覽

1 2

3 4

框架特性

  • 動態配置底層框架為OkHttp、HttpURLConnection
  • RxJava完美結合,支持異步請求、支持同步請求
  • 多文件上傳,支持大文件上傳,表單提交數據
  • 文件下載、上傳下載、上傳和下載的進度回調、錯誤回調
  • 支持Json、xml、Map、List的提交
  • 完美的Http緩存模式,可指定緩存到數據庫、SD卡,緩存數據已安全加密
    • 在6.0以上手機緩存到SD卡時需要請求運行時權限:AndPermission
  • 自定義Request,直接請求JsonObject、JavaBean等
  • Cookie的自動維持,App重啟、關開機后還持續維持
  • http 301 302 303 304 307重定向,支持多層嵌套重定向
  • Https、自簽名網站Https的訪問、支持雙向驗證
  • 失敗重試機制,支持請求優先級
  • GET、POST、PUT、PATCH、HEAD、DELETE、OPTIONS、TRACE等請求協議
  • 用隊列保存請求,平均分配多線程的資源,支持多個請求並發
  • 支持取消某個請求、取消指定多個請求、取消所有請求

使用方法

AndroidStudio使用方式

  • 如果使用HttpURLConnection作為網絡層:
compile 'com.yolanda.nohttp:nohttp:1.1.0'
  • 1
  • 1
  • 如果要使用OkHttp作為網絡層,請再依賴:
compile 'com.yanzhenjie.nohttp:okhttp:1.1.0'
  • 1
  • 1

Eclipse使用方式

初始化

NoHttp初始化需要一個Context,最好在ApplicationonCreate()中初始化,記得在manifest.xml中注冊Application

一般初始化

直接初始化后,一切采用默認設置。

NoHttp.initialize(this);
  • 1

高級自定義初始化

  • 超時配置,默認10s
NoHttp.initialize(this, new NoHttp.Config() // 設置全局連接超時時間,單位毫秒 .setConnectTimeout(30 * 1000) // 設置全局服務器響應超時時間,單位毫秒 .setReadTimeout(30 * 1000) );
  • 1
  • 配置緩存,默認保存在數據庫
NoHttp.initialize(this, new NoHttp.Config() ... // 保存到數據庫 .setCacheStore( new DBCacheStore(this).setEnable(true) // 如果不使用緩存,設置false禁用。 ) // 或者保存到SD卡 .setCacheStore( new DiskCacheStore(this) ) );

  • 配置Cookie保存的位置,默認保存在數據庫
NoHttp.initialize(this, new NoHttp.Config() ... // 默認保存數據庫DBCookieStore,開發者可以自己實現。 .setCookieStore( new DBCookieStore(this).setEnable(false) // 如果不維護cookie,設置false禁用。 ) );
  • 1
  • 配置網絡層
NoHttp.initialize(this, new NoHttp.Config() ... // 使用HttpURLConnection .setNetworkExecutor(new URLConnectionNetworkExecutor()) // 使用OkHttp .setNetworkExecutor(new OkHttpNetworkExecutor()) );

需要的權限

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

友好的調試模式

Logger.setDebug(true);// 開啟NoHttp的調試模式, 配置后可看到請求過程、日志和錯誤信息。 Logger.setTag("NoHttpSample");// 設置NoHttp打印Log的tag。
  • 1

開啟NoHttp的調試模式后可看到請求過程、日志和錯誤信息,基本不用抓包。可以看到請求頭、請求數據、響應頭、Cookie等,而且打印出的Log非常整齊。

所以說,如果你使用過程中遇到什么問題了,開啟調試模式,一切妖魔鬼怪都會現形的。

第三方異步框架

RxJava
可以與RxJava、RxAndroid、RxBus、EventBus等第三方異步任務框架完美結合使用,這里在demo中給出了和RxJava一起使用的代碼。具體的封裝請參考Demo的RxNoHttp。

Request<UserInfo> request = new JavaBeanRequest<>(url, UserInfo.class); RxNoHttp.request(this, request, new SimpleSubscriber<Response<UserInfo>>() { @Override public void onNext(Response<YanZhenjie> entityResponse) { // 直接拿到實體對象 UserInfo userInfo = entiryResponse.get(); } });

請求隊列

RequestQueue requestQueue = NoHttp.newRequestQueue();
// 如果要指定並發值,傳入數字即可:NoHttp.newRequestQueue(3); // 發起請求 requestQueue.add(what, request, responseListener);
  • 添加請求到隊列時有一個what,這個what會在responseLisetener響應時回調給開發者,所以開發者可以用一個responseLisetener接受多個請求的響應,用what來區分結果。而不用像有的框架一樣,每一個請求都要new一個callback。
  • 強烈建議把生成隊列寫成懶漢單例模式,因為每新建隊列就會new出相應個數的線程來,同時只有線程數固定了,隊列的作用才會發揮到最大。

請求類型

String請求

Request<String> request = NoHttp.createStringRequest(url, RequestMethod.GET);
requestQueue.add(0, request, listener);

Json請求

// JsonObject Request<JSONObject> objRequest = NoHttp.createJsonObjectRequest(url, RequestMethod.POST); requestQueue.add(0, objRequest, listener); // JsonArray Request<JSONArray> arrayRequest = NoHttp.createJsonArrayRequest(url, RequestMethod.PUT); requestQueue.add(0, arrayRequest, listener);

Bitmap請求

Request<Bitmap> request = NoHttp.createImageRequest(url, RequestMethod.DELETE);
requestQueue.add(0, request, listener);

請求FastJson與Gson

// FastJson Request<JSONObject> request = new FastJsonRequest(url, RequestMethod.POST); requestQueue.add(0, request, listener);

直接請求JavaBean

// 內部使用Gson、FastJson解析成JavaBean Request<UserInfo> request = new JavaBeanRequest(url, RequestMethod.GET); requestQueue.add(0, request, listener);
  • 1

添加參數

Request<JSONObject> request = new JavaBeanRequest(url, RequestMethod.POST); .add("name", "yoldada") // String類型 .add("age", 18) // int類型 .add("sex", '0') // char類型 .add("time", 16346468473154) // long類型 // 添加Bitmap .add("head", new BitmapBinary(bitmap)) // 添加File .add("head", new FileBinary(file)) // 添加ByteArray .add("head", new ByteArrayBinary(byte[])) // 添加InputStream .add("head", new InputStreamBinary(inputStream))

文件上傳實現了http表單的標准協議,滿足了廣大開發者的需求,有以下幾種形式:

  • 單個文件
Request<String> request = ...
request.add("file", new FileBinary(file));
  • 1
  • 上傳多個文件、多個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 BitmapBinary(Bitmap));

  • 上傳多個文件、一個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 BitmapBinary(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);

提交請求包體

提交Body分為提交Json、提交String、提交Xml、提交流等,具體用法如下:

// 提交普通String request.setDefineRequestBody(String, ContentType); // 提交json字符串 request.setDefineRequestBodyForJson(JsonString) // 提交jsonObject對象,其實還是json字符串 request.setDefineRequestBodyForJson(JSONObject) // 提交xml字符串 request.setDefineRequestBodyForXML(XmlString) // 提交字體Body,比如File(這跟表單上傳不一樣的),可以轉為InputStream來提交 request.setDefineRequestBody(InputStream, ContentType)

同步請求

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

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

五大緩存模式

NoHttp的緩存非常強大,支持緩存到數據庫、換到SD卡等,並且不論緩存在數據庫或者SD,NoHttp都把數據進行了加密,需要在初始化的時候配置緩存的位置。

需要注意的是,在6.0以上的手機中如果要緩存在SD卡,需要在請求之前,需要請求運行時權限,如果你不懂運行時權限,可以看這個項目:AndPermission

NoHttp.initialize(this, new NoHttp.Config() ... // 保存到數據庫 .setCacheStore( new DBCacheStore(this).setEnable(true) // 如果不使用緩存,設置false禁用。 ) // 或者保存到SD卡 .setCacheStore( new DiskCacheStore(this) ) );

  • 1、Default模式,實現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。

請求String,緩存String:

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);

文件下載

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

文件下載也是隊列,隊列和開頭所說的請求的隊列是一樣的。

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

  • 暫停或者停止下載
downloadRequest.cancel();

  • 監聽下載過程
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) { // 下載被取消或者暫停 } };

取消請求

NoHttp支持取消某個請求、取消指定多個請求、取消所有請求。

  • 取消單個請求
    直接調用請求對象的cancel方法。
request.cancel();
  • 1
  • 從隊列中取消指定的請求
    在請求之前給請求set一個sign,取消的時候調用隊列的cancelBySign就可以取消掉所有指定這個sign的請求。
request1.setCancelSign(sign);
request2.setCancelSign(sign);
...

// 取消隊列中多個用sign標志的請求 queue.cancelBySign(sign);
  • 取消隊列中所有請求
queue.cancelAll();
  • 1

 

停止隊列

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

RequestQueue queue = NoHttp.newRequestQueue();
...

queue.stop();

自定義請求

NoHttp的所有自帶請求都是繼承RestRequest類,所以我們自定義請求也需要繼承RestRequest,泛型寫自己想要請求的數據類型,最后在parseResponse()方法中解析服務器數據成自己自己想要的數據類型即可。
* FastJsonRequest

public class FastJsonRequest extends RestRequestor<JSONObject> { public FastJsonRequest(String url) { this(url, RequestMethod.GET); } public FastJsonRequest(String url, RequestMethod requestMethod) { super(url, requestMethod); } @Override public JSONObject parseResponse(Headers header, byte[] body) throws Throwable { String result = StringRequest.parseResponseString(headers, body); return JSON.parseObject(result); } }

  • JavaBeanRequest,利用FastJson、Gson等把數據直接轉為JavaBean
public class JavaBeanRequest<T> extends RestRequest<T> { private Class<T> clazz; public JavaBeanRequest(String url, Class<T> clazz) { this(url, RequestMethod.GET, clazz); } public JavaBeanRequest(String url, RequestMethod requestMethod, Class<T> clazz) { super(url, requestMethod); this.clazz = clazz; } @Override public T parseResponse(Headers header, byte[] body) throws Throwable { String response = StringRequest.parseResponseString(header, body); // 這里如果數據格式錯誤,或者解析失敗,會在失敗的回調方法中返回 ParseError 異常。 return JSON.parseObject(response, clazz); } }
  • 使用自定義請求
// 使用FastJson自定義請求 Request<JSONObject> request = new FastJsonRequest(url, requestMethod); queue.add(what, mRequest, listener); ... // 直擊請求JavaBean Request<UserInfo> request = new JavaBeanRequest(url, UserInfo.class); queue.add(what, request, listener);

代碼混淆

NoHttp設計到兼容高版本系統的api采用反射調用,所以所有類都可以被混淆,如果你非要keep的話,如下配置即可。

  • 原生NoHttp混淆
-dontwarn com.yolanda.nohttp.** -keep class com.yolanda.nohttp.**{*;}

  • 如果使用okhttp的版本
// nohttp -dontwarn com.yolanda.nohttp.** -keep class com.yolanda.nohttp.**{*;}  // nohttp-okhttp -dontwarn com.yanzhenjie.nohttp.** -keep class com.yanzhenjie.nohttp.**{*;}  // okhttp -dontwarn okhttp3.** -keep class okhttp3.** { *;} -dontwarn okio.** -keep class okio.** { *;} 
 


免責聲明!

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



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