以下是官方文檔描述此庫的特色:
php
All requests are made outside of your app’s main UI thread, but any callback logic will be executed on the same thread as the callback was created using Android’s Handler message passing.
•Using upstream HttpClient of version 4.3.6 instead of Android provided DefaultHttpClient
•Compatible with Android API 23 and higher
•Make asynchronous HTTP requests, handle responses in anonymous callbacks
•HTTP requests happen outside the UI thread
•Requests use a threadpool to cap concurrent resource usage
•GET/POST params builder (RequestParams)
•Multipart file uploads with no additional third party libraries
•Streamed JSON uploads with no additional libraries
•Handling circular and relative redirects
•Tiny size overhead to your application, only 90kb for everything
•Automatic smart request retries optimized for spoĴy mobile connections
•Automatic gzip response decoding support for super-fast requests
•Binary protocol communication with BinaryHttpResponseHandler
•Built-in response parsing into JSON with JsonHttpResponseHandler
•Saving response directly into file with FileAsyncHttpResponseHandler
•Persistent cookie store, saves cookies into your app’s SharedPreferences
•Integration with Jackson JSON, Gson or other JSON (de)serializing libraries with BaseJsonHttpResponseHandler
•Support for SAX parser with SaxAsyncHttpResponseHandler
•Support for languages and content encodings, not just UTF-8java
•一、兼容Android API23或更高版本
•二、發送異步的http請求,在匿名的回調callback中處理響應response
•三、Http的請求發生在主線程以外
•四、使用線程池處理併發請求
•五、使用RequestParams構造GET、POST請求參數
•六、流式Json上傳,無需三方庫支持
•七、能處理環形和相對重定向
•八、內置multiPart file 上傳,無需第三方庫支持
•九、相比app來講庫很小,僅僅只有90k
•十、針對移動鏈接自動智能的請求重試優化機制
•十一、自動的gzip響應解碼
•十二、支持字節流響應處理 BinaryHttpResponseHandler
•1三、內置Json文本響應處理 JsonHttpResponseHandler
•1四、持久化Cookie信息,將Cookie信息保存在應用的SharedPreference中
•1五、經過實現抽象類BaseJsonHttpResponseHandler能夠無縫對接三方Json解析庫
•1六、支持SAX解析器 SaxAsyncHttpResponseHandler
•1七、支持各類語言和content編碼,不止是UTF-8cookie
Android-Async-Http 源碼版本1.4.9
在AsyncHttpClient的構造方法中有對鏈接各類參數的設置,並實例化了一個默認的線程池threadPool(Executors.newCachedThreadPool)用於提交請求任務AsyncHttpRequest,接着初始化了httpClient,並給請求和響應添加了攔截器以實現自動的gzip解碼,調用AsyncHttpRequest實例的get post等方法時最終會調用sendRequest方法,sendRequest方法接收httpClient、responseHandler、uriRequest等參數,在方法內部會構造請求的AsyncHttpRequest對象(newAsyncHttpRequest),並經過threadPool.submit(request)方法提交到線程池中,何爲異步就體如今這裏。
AsyncHttpRequest實現了Runnable接口,它的run方法就是核心代碼,調用responseHandler.sendxxx 方法以實現各類方法回調和請求結果投遞,在makeRequestWithRetries中有重試的邏輯,具體在retryHandler中有重試次數的判斷,當重試次數超過最大值時(默認是5次),跳出while循環,這裏重試的邏輯和Volley中的處理相似 。
其中AsyncHttpClient中默認的線程池沒有核心線程,只有work線程,且工做線程的存活時間是60s,若是此種線程池不能知足須要,能夠實現本身的線程池,並調用setThreadPool方法。
其中在調用AsyncHttpClient中各類請求方法時,會傳入請求響應的各式xxxResponseHandler,針對不一樣的響應數據類型,有TextHttpResponseHandler、JsonHttpResponseHandler、FileHttpResponseHandler等,這些xxxResponseHandler中封裝了Handler和Looper,由於構造Handler是須要先有Looper的,而looper的初始化是在AsyncHttpResponseHandler構造函數中,
this.looper = looper == null ? Looper.myLooper() : looper,即若是沒有傳入looper則使用當前線程的looper(即建立xxxResponseHandler的線程,多是主線程也多是子線程)。 這些xxxResponseHandler都繼承自AsyncHttpResponseHandler類,並實現了
onSuccess(int statusCode, Header[] headers, byte[] responseBody) 和 onFailure(int statusCode, Header[] headers, byte[] responseBody, Throwable error)方法,以處理不一樣返回數據類型的響應。
如上敘述印證了2 、三、四、十、11條結論。
---------------------------------------------------------------------------------------------------------------------------------------------併發
上傳圖片文件到chuantu.biz,代碼以下app
AsyncHttpClient httpClient = new AsyncHttpClient(); RequestParams params = new RequestParams(); try { String filePath = getBaseContext().getExternalCacheDir().getPath() + File.separator + "IMG_20171106_202814.jpg"; File file = new File(filePath); if (file.exists()) { params.put("uploadimg", file, "image/jpeg"); } } catch (FileNotFoundException e) { e.printStackTrace(); } httpClient.setProxy("172.20.10.2", 8888); httpClient.post(this, "http://www.chuantu.biz/upload.php", /*headers,*/ params,/* null,*/ new TextHttpResponseHandler() { @Override public void onSuccess(int statusCode, Header[] headers, String responseBody) { printHeaders(headers); Log.d(TAG, responseBody); } @Override public void onFailure(int statusCode, Header[] headers, String responseBody, Throwable error) { } });
如上印證了5 、8 兩條特性。異步
上傳文件時,會調用RequestParams中的createMultipartEntity方法,其中SimpleMulitpartEntity的addPart方法會添加待寫入流中的文件信息,以後將文件內容的字節寫入到流中,具體見SimpleMultipartEntity的writeTo方法,其中SimpleMultipartEntity類實現了HttpEntity接口,其中重寫了getContentType方法,此方法中返回標識性的header信息,Content-Type:multipart/form-data;boundary= xxxxxx, 分界線標識的字符串是在數字大小寫字符等字符中隨機抽取出來的30個字符組成。async
須要注意到構造AsyncHttpRequest時最後的參數context, 若是context不爲空,請求會被放到
Map中,以便在Activity onPause的時候或者onDestory的時候取消掉無用的請求等。
-------------------------------------------------------------------------------------------------------------------ide
BaseJsonHttpResponseHandler的使用函數
先添加Gson依賴,compile 'com.google.code.gson:gson:2.8.1'
這裏以kuaidi100的快遞數據爲例:http://www.kuaidi100.com/query?type=xxx&postid=xxxx
先建立一個快遞數據類的實體(這裏字段並不全,只是爲了說明問題,具體能夠自行調試接口)oop
public class Express { public String message; public String nu; public int isCheck; public String com; public int status; public int state; public Express(String message, String nu, int isCheck, String com, int status, int state) { this.message = message; this.nu = nu; this.isCheck = isCheck; this.com = com; this.status = status; this.state = state; } @Override public String toString() { return "Express{" + "message='" + message + '\'' + ", nu='" + nu + '\'' + ", isCheck=" + isCheck + ", com='" + com + '\'' + ", status=" + status + ", state=" + state + '}'; } }
建立RequestParams 發起GET請求
RequestParams params = new RequestParams(); params.put("type", "shunfeng"); params.put("postid", "384566812983"); httpClient.get("http://www.kuaidi100.com/query", params, new BaseJsonHttpResponseHandler<Express>() { @Override public void onSuccess(int statusCode, Header[] headers, String rawJsonResponse, Express response) { Log.d(TAG, "response = " + response); } @Override public void onFailure(int statusCode, Header[] headers, Throwable throwable, String rawJsonData, Express errorResponse) { } @Override protected Express parseResponse(String rawJsonData, boolean isFailure) throws Throwable { Gson gson = new Gson(); return gson.fromJson(rawJsonData, Express.class); } });