async-http-client開源庫學習筆記
在進行Android應用開發時,網絡通信功能是不可或缺的模塊之一。為了能讓應用保持好的用戶交互體驗和高效的網絡通信性能,程序員GG要進行大量的多線程開發以及線程之間的并發同步處理,稍有不慎,傷得可就不僅僅是測試軟妹子的心,還有可能是自己的飯碗。 async-http-client開源庫為程序員GG封裝了http數據通信的各種底層處理,包括異步、數據轉換、文件分段下載等等,我們只需要關注功能的本身所需要的數據處理部分就可以安心泡妹子了。
0. 文前閑話
作為一個Android開發的大齡初學者,面對撲面而來的各種姿勢的Android的開源組件,讓人倍感窒息,難以應對。無奈為了養家糊口,雖然已近不惑,人老珠黃,也只能廢寢忘食,逐個體位細細揣摩研究,不斷以身實踐,爭取早日小成。
話說那是一個陽光明媚的下午,我坐在街口轉角處優雅的網絡會所里,品著一杯上好的Coca-Cola,研讀著oschina客戶端源碼,身旁不時傳來:“一起上搞死他,他沒藍了...!”。
從火蟻(oschina客戶端的開發者之一,向他們致敬)那里知道了async-http-client開源庫,為了千千萬萬個沒過英語四級的程序猿GG,就在這里翻譯個作者寫的"用戶說明書"先...
1. async-http-client開源庫簡介
async-http-client庫是一個基于回調函數的Http異步通信客戶端Android組件,是在Apache的HttpClient庫的基礎上開發構建而成的。這里的異步,是指它所有的網絡請求都是在app的UI線程之外的獨立工作線程中執行。而開發者通過利用Android的消息處理機制,把我們所需要編寫的回調函數放在這個回調函數的創建線程中執行(一般就是UI線程),所以使用起來非常方便,有了它,媽媽再也不用擔心我被多線程同步搞死了。除了能應用在開發普通App上,還可以用來開發Service或后臺線程,async-http-client庫可以自已分辨是被用在哪一種應用下,不需要額外的設置。
1.1 特點
-
異步方式發起Http請求,可以使用匿名回調函數處理網絡應答;
-
在UI主線程之外的工作線程發起Http請求;
-
通過使用線程池解決了資源并發的效率問題;
-
通過使用RequestParams類,可完成GET/POST的參數構建;
-
支持文件的分段下載功能;
-
支持上傳JSON數據流;
-
對重定向循環、重定向相對路徑異常進行了處理
-
代碼體積小,全部功能只占90kb;
-
專門針對移動網絡的不穩定性,對請求重發進行了優化,實現了自動智能處理;
-
傳輸時支持數據壓縮,可自動對應答進行gzip解壓處理;
-
使用BinaryHttpResponseHandler,可進行較底層的tcp/ip協議數據通信;
-
JsonHttpResponseHandler內嵌JSON語法分析功能,可完成JSON數據解析;
-
FileAsyncHttpResponseHandler可直接將應答保存到本地文件中;
-
支持cookie的持久化,可使用App的SharedPreferences保存cookie信息;
-
通過BaseJsonHttpResponseHandler可與Jackson JSON, Gson等第三方JSON框架庫集成;
-
SaxAsyncHttpResponseHandler支持SAX語法分析
-
除了UTF-8,還支持其它語言編碼。
1.2 使用async-http-client的大型應用
-
Instagram
-
Pinterest
-
Frontline Commando (Glu Games)
-
Heyzap
-
Pose
(以上應用我一個都沒用過,反正說明async-http-client很diao就對了)
2. async-http-client庫的安裝和基本應用
2.1 基本應用方法
1. 在Gradle build腳本中增加
dependencies { compile 'com.loopj.android:android-async-http:1.4.8' }
2. 引入http包
import com.loopj.android.http.*;
3. 創建AsyncHttpClient 實例,并發出請求
AsyncHttpClientclient = new AsyncHttpClient(); client.get("http://www.google.com", new AsyncHttpResponseHandler(){ @Override public void onStart(){ // called before request is started } @Override public void onSuccess(int statusCode, Header[] headers, byte[] response){ // called when response HTTP status is "200 OK" } @Override public void onFailure(int statusCode, Header[] headers, byte[] errorResponse, Throwablee){ // called when response HTTP status is "4XX" (eg. 401, 403, 404) } @Override public void onRetry(int retryNo){ // called when request is retried } });
2.2 推薦使用方法:創建靜態Http客戶端
創建AsyncHttpClient的靜態實例進行通信更加方便,以使用推ter提供的Api為例(此處使用推ter作例子,站在大墻里面的我們看看就行了):
import com.loopj.android.http.*; public class 推terRestClient { private static final String BASE_URL = "https://api.推ter.com/1/"; private static AsyncHttpClient client = new AsyncHttpClient(); public static void get(String url, RequestParams params, AsyncHttpResponseHandler responseHandler) { client.get(getAbsoluteUrl(url), params, responseHandler); } public static void post(String url, RequestParams params, AsyncHttpResponseHandler responseHandler) { client.post(getAbsoluteUrl(url), params, responseHandler); } private static String getAbsoluteUrl(String relativeUrl) { return BASE_URL + relativeUrl; } }
推terRestClient 類中創建了一個AsyncHttpClient的靜態實例,通過靜態實例與推ter進行數據通信,共有兩個對外的接口函數get,set,也都是靜態的。下面是如何在代碼中使用這個類:
import org.json.*; import com.loopj.android.http.*; class 推terRestClientUsage { public void getPublicTimeline() throws JSONException { 推terRestClient.get("statuses/public_timeline.json", null, new JsonHttpResponseHandler() { @Override public void onSuccess(int statusCode, Header[] headers, JSONObject response) { // If the response is JSONObject instead of expected JSONArray } @Override public void onSuccess(int statusCode, Header[] headers, JSONArray timeline) { // Pull out the first event on the public timeline JSONObject firstEvent = timeline.get(0); String tweetText = firstEvent.getString("text"); // Do something with the response System.out.println(tweetText); } }); } }
這里使用了匿名回調函數,并且是JsonHttpResponseHandler類型,它內嵌了Json語言解析器,可直接在處理函數中使用對應答數據解析后的Json數據,真是即方便又快捷。
3. 使用PersistentCookieStore進行Cookie的持久化存儲
async-http-client庫包含一個PersistentCookieStore類,這個類實現了CookieStore接口(源自Apache HttpClient包),可自動將cookie信息保存到應用的SharedPreferences儲存中。
如果你的應用需要使用cookie維護用戶授權session,這是非常有用,方便的。即使關閉了app或重新啟動app,應用也可以保持用戶已登錄的狀態。
首先創建一個AsyncHttpClient實例:
AsyncHttpClient myClient = new AsyncHttpClient();
為這個實例設置一個新建的PersistentCookieStore的實例以進行cookie存儲,調用這個PersistentCookieStore實例的構造函數時,使用一個activity或application context作參數(一般用this就可以了):
PersistentCookieStore myCookieStore = new PersistentCookieStore(this); myClient.setCookieStore(myCookieStore);
這樣由服務端接收到的cookie將會自動存儲在你的android設備上。如果要添加自己的cookie,只需要構建一個新的cookie并調用addCookie函數:
BasicClientCookie newCookie = new BasicClientCookie("cookiesare", "awesome"); newCookie.setVersion(1); newCookie.setDomain("mydomain.com"); newCookie.setPath("/"); myCookieStore.addCookie(newCookie);
4. 使用RequestParams增加GET/POST參數
4.1 為請求增加參數
大部分應用的url請求都需要帶各種參數,在Get/Post請求時增加參數,可使用RequestParams類。
可以使用以下三種方法構建RequestParams實例:
1. 創建一個空的RequestParams實例,并增加參數:
RequestParams params = new RequestParams(); params.put("key", "value"); params.put("more", "data");
2. 只有一個參數,創建RequestParams實例:
RequestParams params = new RequestParams("single", "value");
3. 利用已存在的Map鍵值對創建RequestParams實例:
HashMap<String, String> paramMap = new HashMap<String, String>(); paramMap.put("key", "value"); RequestParams params = new RequestParams(paramMap);
4.2 利用RequestParams上傳文件
RequestParams類還可以用來實現文件分段上傳,有以下三種實現方式:
1. 將InputStream作為參數加入RequestParams:
InputStream myInputStream = blah; RequestParams params = new RequestParams(); params.put("secret_passwords", myInputStream, "passwords.txt");
2. 直接將File對象增加到RequestParams中:
File myFile = new File("/path/to/file.png"); RequestParams params = new RequestParams(); try { params.put("profile_picture", myFile); } catch(FileNotFoundException e) {}
3. 使用二進制字節數組:
byte[] myByteArray = blah; RequestParams params = new RequestParams(); params.put("soundtrack", new ByteArrayInputStream(myByteArray), "she-wolf.mp3");
5. 使用FileAsyncHttpResponseHandler下載二進制數據
FileAsyncHttpResponseHandler用來獲取二進制數據,比如圖像、聲音等文件。
AsyncHttpClient client = new AsyncHttpClient(); client.get("https://example.com/file.png", new FileAsyncHttpResponseHandler(/* Context */ this) { @Override public void onSuccess(int statusCode, Header[] headers, File response) { // Do something with the file `response` } });
6. 為HTTP通信增加授權認證
在實際應用環境中,某些服務器資源需要用戶名/密碼授權認證才能訪問,這類資源訪問需要使用HTTP Basic Access Authentication協議,請求才能被處理。可以使用setBasicAuth函數提供認證信息。
為主機或域名訪問設置用戶名/密碼,默認狀態認證信息對所有主機、端口或域名有效。
AsyncHttpClient client = new AsyncHttpClient(); client.setBasicAuth("username","password/token"); client.get("https://example.com");
更為推薦的方式是對特定的主機或端口提供授權認證信息:
AsyncHttpClient client = new AsyncHttpClient(); client.setBasicAuth("username","password", new AuthScope("example.com", 80, AuthScope.ANY_REALM)); client.get("https://example.com");
來自:http://my.oschina.net/u/725054/blog/494494