国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 系統 > Android > 正文

Android使用OkHttp進行網絡同步異步操作

2019-10-21 21:46:23
字體:
來源:轉載
供稿:網友

OkHttp是一個Java和Android的HTTP和HTTP/2的客戶端,負責發送HTTP請求以及接受HTTP響應。

一、使用OkHttp

OkHttp發送請求后,可以通過同步或異步地方式獲取響應。下面就同步和異步兩種方式進行介紹。

1.1、同步方式

發送請求后,就會進入阻塞狀態,知道收到響應。下面看一個下載百度首頁的例子:

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();    }

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

1.2、異步方式

異步方式是在回調中處理響應的,同樣看下載百度首頁的例子:

 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());      }    });

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

1.3、Request、Response、Call

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

Request 

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

Response 

響應是對請求的回復,包含狀態碼、HTTP頭和主體部分。

重寫請求 

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

重寫響應 

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

請求重定向 

當請求的URL移動了,web服務器會返回一個302的狀態碼并指明文件的新地址。OkHttp將會重定向獲取最終的響應。 

請求重試 

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

Call 

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

二、攔截器

攔截器是一個監視、重寫、重試請求的強有力機制。攔截器可以串聯。 

Android,OkHttp,網絡同步,異步

從圖中可以看出,攔截器分為應用攔截器和網絡攔截器兩種。應用攔截器是在發送請求之前和獲取到響應之后進行操作的,網絡攔截器是在進行網絡獲取前進行操作的。

2.1、應用攔截器

下面定義一個應用攔截器,用于在請求發送前打印URL以及接受到響應后打印內容。

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實現了Interceptor接口。首先從chain中得到請求,然后打印請求;然后調用proceed方法處理請求得到響應,然后打印響應。調用代碼如下:

 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();    }

可以看到通過調用addInterceptor方法添加應用攔截器。

2.2、網絡攔截器

網絡攔截器的使用和應用攔截器類似,只是調用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();    }

下面是運行結果:

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/}

可以發現,攔截器運行了兩次。一次是初始請求”http://www.taobao.com“,一次是請求重定向”https://www.taobao.com“。

2.3、應用攔截器和網絡攔截器的比較

每個攔截器由它各自的優勢。 

應用攔截器 

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

網絡攔截器 

- 可以操作中間狀態的響應,比如重定向和重試 
- 不調用緩存的響應 
- 可以觀察整個網絡上傳輸的數據 
- 獲得攜帶請求的Connection

2.4、重寫請求

攔截器可以添加、移除或者替換請求的頭信息,也可以改變傳輸的主體部分。下面的一個攔截器對請求主體進行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、重寫響應

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

/** 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(); }};

三、總結

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

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持VEVB武林網。


注:相關教程知識閱讀請移步到Android開發頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 如东县| 慈溪市| 抚宁县| 陆河县| 土默特左旗| 高碑店市| 乌兰县| 武乡县| 务川| 铜山县| 莱西市| 金堂县| 宁南县| 吴忠市| 河南省| 莎车县| 玛纳斯县| 海林市| 沈阳市| 宁晋县| 库伦旗| 聂拉木县| 雷州市| 定日县| 昌乐县| 连江县| 隆回县| 布尔津县| 青浦区| 神池县| 河间市| 河北区| 达拉特旗| 同心县| 乐山市| 桦甸市| 韶山市| 谢通门县| 泊头市| 东乡| 长丰县|