天天看點

Android網絡請求:OkHttp實戰

android網絡請求是個耗時的操作,一定要在子線程中運作,添加網絡權限,目前有很多流行的網絡架構。比如okhttp,volley,xutils等等。今天主要介紹okhttp的使用,後續分享給多,比如socket網絡請求,檔案上傳下載下傳。

一,HTTP協定的主要特點

HTTP協定的主要特點可概括如下:

1.支援客戶/伺服器模式。

2.簡單快速:客戶向伺服器請求服務時,隻需傳送請求方法和路徑。請求方法常用的有GET、HEAD、POST。每種方法規定了客戶與伺服器聯系的類型不同。由于HTTP協定簡單,使得HTTP伺服器的程式規模小,因而通信速度很快。

3.靈活:HTTP允許傳輸任意類型的資料對象。正在傳輸的類型由Content-Type加以标記。

4.無連接配接:無連接配接的含義是限制每次連接配接隻處理一個請求。伺服器處理完客戶的請求,并收到客戶的應答後,即斷開連接配接。采用這種方式可以節省傳輸時間。

5.無狀态:HTTP協定是無狀态協定。無狀态是指協定對于事務處理沒有記憶能力。缺少狀态意味着如果後續處理需要前面的資訊,則它必須重傳,這樣可能導緻每次連接配接傳送的資料量增大。另一方面,在伺服器不需要先前資訊時它的應答就較快。

詳見原文:HTTP協定詳解(真的很經典)

二,OKHttp介紹

An HTTP & HTTP/2 client for Android and Java applications. For more information see the website and the wiki.前往OkHttp官網

使用okhttp很簡單,它的請求/響應 API設計,運用了流利的builder,確定方式多樣而又固定,支援異步請求和回調。它支援android 2.3或以上,jdk版本要求不低于1.7。

okhttp的主要特點:

  1. HTTP/2支援共享一個socket,發送多個請求給相同的主機。
  2. 連接配接池減少了請求的潛在因素。
  3. 明顯的GZIP壓縮下載下傳大小。
  4. 響應緩存避免網絡重複請求。

確定所有的網絡請求隻有一個OkHttpClient執行個體,可以用單例模式。也可以如下:

public static OkHttpClient okHttpClient = new OkHttpClient();
           

okhttp發送請求,封裝的方法,必須在子線程運作。另外回調方法是在子線程中,要更新UI必須在主線程,自己處理。下面的方法中的OkHttpClient執行個體統一用上面生成的。

三,okhttp發送get請求

示範基本的用法,不懂的地方可以github下載下傳源碼研究。

//OKHTTP GET
    public static String get(String url){
        Request request = new Request.Builder().url(url).build();
        Response response = null;
        try {
            response =  new OkHttpClient().newCall(request).execute();
            if (response.isSuccessful()) {
                return response.body().string();
            } else {
                throw new IOException("Unexpected code " + response);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
       return "";
    }
           

四,OKHttp建構RequestBody

發送post的請求,比較普遍。無論有一個參數,多個參數,或者檔案上傳,都可以建構特定的RequestBody發送請求。

1.發送一個鍵值對。

2.發送多個參數,建構表單一樣的請求參數。

RequestBody requestBody = new FormBody.Builder()
                .add("param1", "value1")
                .add("param12", "value2")
                .build();
           

3. post json字元串

MediaType JSON = MediaType.parse("application/json; charset=utf-8");
RequestBody body = RequestBody.create(JSON, json);
           

4. 檔案上傳

MediaType,檔案類型标示,通常”application/octet-stream”就可以,比如jpg圖檔,可以MediaType.parse(“image/jpg”)。表單參數根據項目需要自行調整。

final MediaType mediaType = MediaType.parse("application/octet-stream");
            MultipartBody.Builder builder = new MultipartBody.Builder().setType(MediaType.parse("multipart/form-data"));
            builder.addFormDataPart("description", description);
            builder.addFormDataPart("file", fileName, RequestBody.create(mediaType, uploadFile));
   //建構請求體
  RequestBody requestBody = builder.build();
           

五,發送的post請求的方法

//使用Request的post方法來送出請求體RequestBody
    public static String post(String url, RequestBody requestBody) throws IOException {
        Request request = new Request.Builder()
                .url(url)
                .post(requestBody)
                .build();
        Response response = okHttpClient.newCall(request).execute();
        if (response.isSuccessful()) {
            return response.body().string();
        } else {
            throw new IOException("Unexpected code " + response);
        }
    }
           

六,Headers相關。

先看官方對header和addHeader兩種方法的解釋:

/**
     * Sets the header named {@code name} to {@code value}. If this request already has any headers
     * with that name, they are all replaced.
     */
    public Builder header(String name, String value) {
      headers.set(name, value);
      return this;
    }

    /**
     * Adds a header with {@code name} and {@code value}. Prefer this method for multiply-valued
     * headers like "Cookie".
     *
     * <p>Note that for some headers including {@code Content-Length} and {@code Content-Encoding},
     * OkHttp may replace {@code value} with a header derived from the request body.
     */
    public Builder addHeader(String name, String value) {
      headers.add(name, value);
      return this;
    }
           

意思就是說,header是給已有的請求頭設定一個值,

addHeader是添加新的請求頭,value的值可以有多個(以英文”,”分開)。例如:

private final OkHttpClient client = new OkHttpClient();

public void run() throws Exception {
  Request request = new Request.Builder()
      .url("https://api.github.com/repos/square/okhttp/issues")
      .header("User-Agent", "OkHttp Headers.java")
      .addHeader("Accept", "application/json; q=0.5")
      .addHeader("Accept", "application/vnd.github.v3+json")
      .build();

  Response response = client.newCall(request).execute();
  if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);
    LogUtils.debug("Server:"+response.header("Server"));
    LogUtils.debug("Date: " + response.header("Date"));
    LogUtils.debug("Vary: " + response.headers("Vary"));
}
           

傳回結果:

Server: GitHub.com
Sat, 30 Apr 2016 01:24:48 GMT
Vary: [Accept, Accept-Encoding]
           

七,總結

okhttp是目前比較流行的網絡架構,開源項目,本文介紹了本人一些常用的用法,不到之處望留言指出。對比了一些網絡架構,還是挺贊的。

有時間再研究研究源碼,未完待續,歡迎交流,杜乾,Dusan,Q 291902259。