-
NoHttp詳細文檔:http://doc.nohttp.net
-
NoHttp公益測試接口:http://api.nohttp.net
支持與RxJava完美結合、支持一句話切換底層為OkHttp,支持緩存數據到數據庫或SD卡和數據庫,並對數據做了加密保護,支持請求Restful風格的接口,比Retrofit更簡單易用。
歡迎加入QQ技術交流群:46523908
效果預覽


框架特性
- 動態配置底層框架為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使用方式
- 如果使用HttpURLConnection作為網絡層:
-
如果使用OkHttp做為網絡層
- 下載nohttp jar包:nohttp原生jar。
- 下載nohttp-okhttp jar包:nohttp和okhttp過渡,只有兩個類。
- 下載okhttp jar包:okhttp原生jar。
- 下載okhttp-url jar包:okhttp和URLConnection的過度。
- 下載okio jar包:okio的包。
-
好多jar啊,所以強烈的999次方建議沒有使用
AndroidStudio的同學趕緊切換過來。
初始化
NoHttp初始化需要一個Context,最好在Application的onCreate()中初始化,記得在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.** { *;}
