async-http-client開源庫學習筆記(一)

0. 文前閒話

    做爲一個Android開發的大齡初學者,面對撲面而來的各類姿式的Android的開源組件,讓人倍感窒息,難以應對。無奈爲了養家餬口,雖然已近不惑,人老珠黃,也只能廢寢忘食,逐個體位細細揣摩研究,不斷以身實踐,爭取早日小成。java

    話說那是一個陽光明媚的下午,我坐在街口轉角處優雅的網絡會所裏,品着一杯上好的Coca-Cola,研讀着oschina客戶端源碼,身旁不時傳來:「一塊兒上搞死他,他沒藍了...!」。android

    從火蟻(oschina客戶端的開發者之一,向他們致敬)那裏知道了async-http-client開源庫,爲了千千萬萬個沒過英語四級的程序猿GG,就在這裏翻譯個做者寫的"用戶說明書"先...json

1. async-http-client開源庫簡介

    async-http-client庫是一個基於回調函數的Http異步通訊客戶端Android組件,是在Apache的HttpClient庫的基礎上開發構建而成的。這裏的異步,是指它全部的網絡請求都是在app的UI線程以外的獨立工做線程中執行。而開發者經過利用Android的消息處理機制,把咱們所須要編寫的回調函數放在這個回調函數的建立線程中執行(通常就是UI線程),因此使用起來很是方便,有了它,媽媽不再用擔憂我被多線程同步搞死了。除了能應用在開發普通App上,還能夠用來開發Service或後臺線程,async-http-client庫能夠自已分辨是被用在哪種應用下,不須要額外的設置。api

1.1 特色

  • 異步方式發起Http請求,可使用匿名回調函數處理網絡應答;數組

  • 在UI主線程以外的工做線程發起Http請求;服務器

  • 經過使用線程池解決了資源併發的效率問題;cookie

  • 經過使用RequestParams類,可完成GET/POST的參數構建網絡

  • 支持文件的分段下載功能;session

  • 支持上傳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的靜態實例進行通訊更加方便,以使用Twitter提供的Api爲例(此處使用Twitter做例子,站在大牆裏面的咱們看看就好了):

import com.loopj.android.http.*;

public class TwitterRestClient {
    private static final String BASE_URL = "https://api.twitter.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;
    }
}

    TwitterRestClient 類中建立了一個AsyncHttpClient的靜態實例,經過靜態實例與Twitter進行數據通訊,共有兩個對外的接口函數get,set,也都是靜態的。下面是如何在代碼中使用這個類:

import org.json.*;
import com.loopj.android.http.*;

class TwitterRestClientUsage {
    public void getPublicTimeline() throws JSONException {
        TwitterRestClient.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");
相關文章
相關標籤/搜索