溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

Android使用OkHttp進(jìn)行網(wǎng)絡(luò)同步異步操作

發(fā)布時間:2020-09-12 03:50:54 來源:腳本之家 閱讀:657 作者:xingfeng_coder 欄目:移動開發(fā)

OkHttp是一個Java和Android的HTTP和HTTP/2的客戶端,負(fù)責(zé)發(fā)送HTTP請求以及接受HTTP響應(yīng)。

一、使用OkHttp

OkHttp發(fā)送請求后,可以通過同步或異步地方式獲取響應(yīng)。下面就同步和異步兩種方式進(jìn)行介紹。

1.1、同步方式

發(fā)送請求后,就會進(jìn)入阻塞狀態(tài),知道收到響應(yīng)。下面看一個下載百度首頁的例子:

OkHttpClient client = new OkHttpClient.Builder().readTimeout(5, TimeUnit.SECONDS).build();
    Request request = new Request.Builder().url("http://www.baidu.com")
        .get().build();
    Call call = client.newCall(request);
    try {
      Response response = call.execute();
      System.out.println(response.body().string());
    } catch (IOException e) {
      e.printStackTrace();
    }

上面的代碼先創(chuàng)建OkHttpClient和Request對象,兩者均使用了Builder模式;然后將Request封裝成Call對象,然后調(diào)用Call的execute()同步發(fā)送請求,最后打印響應(yīng)。

1.2、異步方式

異步方式是在回調(diào)中處理響應(yīng)的,同樣看下載百度首頁的例子:

 OkHttpClient client = new OkHttpClient.Builder().readTimeout(5, TimeUnit.SECONDS).build();
    Request request = new Request.Builder().url("http://www.baidu.com")
        .get().build();
    Call call = client.newCall(request);
    call.enqueue(new Callback() {
      @Override
      public void onFailure(Call call, IOException e) {
        System.out.println("Fail");
      }

      @Override
      public void onResponse(Call call, Response response) throws IOException {

        System.out.println(response.body().string());

      }
    });

同樣是創(chuàng)建OkHttpClient、Request和Call,只是調(diào)用了enqueue方法并在回調(diào)中處理響應(yīng)。
上面介紹了同步、異步獲取請求的步驟,都是比較簡單的。

1.3、Request、Response、Call

上面的代碼中涉及到幾個常用的類:Request、Response和Call。下面分別介紹:

Request

每一個HTTP請求包含一個URL、一個方法(GET或POST或其他)、一些HTTP頭。請求還可能包含一個特定內(nèi)容類型的數(shù)據(jù)類的主體部分。

Response

響應(yīng)是對請求的回復(fù),包含狀態(tài)碼、HTTP頭和主體部分。

重寫請求

當(dāng)將Request提交給OkHttp后,出于正確性和效率的考慮,OkHttp在傳輸請求之前會重寫請求。
OkHttp可能會在請求中添加缺少的請求頭,包括”Content-Length”,”Transfer-Encoding”,”User-Agent”,”HOST”,”Connection”和”Content-Type”等。
有些請求可能有緩存的響應(yīng)。當(dāng)緩存響應(yīng)過時時,OkHttp可以做一個額外的GET請求獲取最新的響應(yīng)。這要求”If-Modified-Since”和”If-None-Match”頭被添加。

重寫響應(yīng)

如果使用了透明壓縮,OkHttp會丟棄”Content-Encoding”和”Content-Length”頭,因為和解壓后的響應(yīng)主體不匹配。
如果一個額外的GET請求成功了,那么網(wǎng)絡(luò)和緩存中的響應(yīng)將會合并。

請求重定向

當(dāng)請求的URL移動了,web服務(wù)器會返回一個302的狀態(tài)碼并指明文件的新地址。OkHttp將會重定向獲取最終的響應(yīng)。

請求重試

有時連接會失敗,那么OkHttp會重試別的路由。

Call

當(dāng)重寫、重定向等時,一個請求可能會產(chǎn)生多個請求和響應(yīng)。OkHttp使用Call抽象出一個滿足請求的模型,盡管中間可能會有多個請求或響應(yīng)。執(zhí)行Call有兩種方式,同步或異步,這在上面已經(jīng)介紹過了。
Call可以在任何線程被取消。

二、攔截器

攔截器是一個監(jiān)視、重寫、重試請求的強(qiáng)有力機(jī)制。攔截器可以串聯(lián)。

Android使用OkHttp進(jìn)行網(wǎng)絡(luò)同步異步操作

從圖中可以看出,攔截器分為應(yīng)用攔截器和網(wǎng)絡(luò)攔截器兩種。應(yīng)用攔截器是在發(fā)送請求之前和獲取到響應(yīng)之后進(jìn)行操作的,網(wǎng)絡(luò)攔截器是在進(jìn)行網(wǎng)絡(luò)獲取前進(jìn)行操作的。

2.1、應(yīng)用攔截器

下面定義一個應(yīng)用攔截器,用于在請求發(fā)送前打印URL以及接受到響應(yīng)后打印內(nèi)容。

public class LogInterceptor implements Interceptor {

  @Override
  public Response intercept(Chain chain) throws IOException {
    Request request = chain.request();
    System.out.println(request.toString());
    Response response = chain.proceed(request);
    System.out.println(response);
    return response;
  }
}

上面的代碼中,LogInterceptor實現(xiàn)了Interceptor接口。首先從chain中得到請求,然后打印請求;然后調(diào)用proceed方法處理請求得到響應(yīng),然后打印響應(yīng)。調(diào)用代碼如下:

 OkHttpClient okHttpClient = new OkHttpClient.Builder().addInterceptor(new LogInterceptor()).build();
    Request request = new Request.Builder().url("http://www.baidu.com")
        .get().build();
    Call call = okHttpClient.newCall(request);
    try {
      call.execute();
    } catch (IOException e) {
      e.printStackTrace();
    }

可以看到通過調(diào)用addInterceptor方法添加應(yīng)用攔截器。

2.2、網(wǎng)絡(luò)攔截器

網(wǎng)絡(luò)攔截器的使用和應(yīng)用攔截器類似,只是調(diào)用OkHttpClient的addNetworkInterceptor方法即可。

OkHttpClient okHttpClient = new OkHttpClient.Builder().addNetworkInterceptor(new LogInterceptor()).build();
    Request request = new Request.Builder().url("http://www.taobao.com")
        .get().build();
    Call call = okHttpClient.newCall(request);
    try {
      call.execute();
    } catch (IOException e) {
      e.printStackTrace();
    }

下面是運(yùn)行結(jié)果:

Request{method=GET, url=http://www.taobao.com/, tag=Request{method=GET, url=http://www.taobao.com/, tag=null}}
Response{protocol=http/1.1, code=302, message=Found, url=http://www.taobao.com/}
Request{method=GET, url=https://www.taobao.com/, tag=Request{method=GET, url=http://www.taobao.com/, tag=null}}
Response{protocol=http/1.1, code=200, message=OK, url=https://www.taobao.com/}

可以發(fā)現(xiàn),攔截器運(yùn)行了兩次。一次是初始請求”http://www.taobao.com“,一次是請求重定向”https://www.taobao.com“。

2.3、應(yīng)用攔截器和網(wǎng)絡(luò)攔截器的比較

每個攔截器由它各自的優(yōu)勢。

應(yīng)用攔截器

- 不需要考慮中間狀態(tài)的響應(yīng),比如重定向或者重試。
- 只會被調(diào)用一次,甚至于HTTP響應(yīng)保存在緩存中。
- 觀察應(yīng)用程序的原意。
- 允許短路,可以不調(diào)用Chain.proceed()方法
- 允許重試和發(fā)送多條請求,調(diào)用Chain.proceed()方法

網(wǎng)絡(luò)攔截器

- 可以操作中間狀態(tài)的響應(yīng),比如重定向和重試
- 不調(diào)用緩存的響應(yīng)
- 可以觀察整個網(wǎng)絡(luò)上傳輸?shù)臄?shù)據(jù)
- 獲得攜帶請求的Connection

2.4、重寫請求

攔截器可以添加、移除或者替換請求的頭信息,也可以改變傳輸?shù)闹黧w部分。下面的一個攔截器對請求主體進(jìn)行Gzip壓縮。

final class GzipRequestInterceptor implements Interceptor {
 @Override public Response intercept(Interceptor.Chain chain) throws IOException {
  Request originalRequest = chain.request();
  if (originalRequest.body() == null || originalRequest.header("Content-Encoding") != null) {
   return chain.proceed(originalRequest);
  }

  Request compressedRequest = originalRequest.newBuilder()
    .header("Content-Encoding", "gzip")
    .method(originalRequest.method(), gzip(originalRequest.body()))
    .build();
  return chain.proceed(compressedRequest);
 }

 private RequestBody gzip(final RequestBody body) {
  return new RequestBody() {
   @Override public MediaType contentType() {
    return body.contentType();
   }

   @Override public long contentLength() {
    return -1; // We don't know the compressed length in advance!
   }

   @Override public void writeTo(BufferedSink sink) throws IOException {
    BufferedSink gzipSink = Okio.buffer(new GzipSink(sink));
    body.writeTo(gzipSink);
    gzipSink.close();
   }
  };
 }
}

2.5、重寫響應(yīng)

同樣地,攔截器可以重寫響應(yīng)的頭部以及主體部分。但是

/** Dangerous interceptor that rewrites the server's cache-control header. */
private static final Interceptor REWRITE_CACHE_CONTROL_INTERCEPTOR = new Interceptor() {
 @Override public Response intercept(Interceptor.Chain chain) throws IOException {
  Response originalResponse = chain.proceed(chain.request());
  return originalResponse.newBuilder()
    .header("Cache-Control", "max-age=60")
    .build();
 }
};

三、總結(jié)

本篇文章主要介紹了OkHttp進(jìn)行GET的同步、異步請求,對于HTTP其他方法,比如POST等都是可以進(jìn)行的,這兒就不過多介紹了,想了解的朋友可以到OkHttp Github地址查看.

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持億速云。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI