OkHttp的深入研究:Jesse Wilson(三)

20 篇文章 0 订阅

OkHttp 2.0

June 23, 2014

OkHttp started as a fork of Android’s HttpURLConnection. That gave us a solid foundation to build upon. Working behind a widely-used API meant that upgrading from AOSP’s HttpURLConnectionto ours was easy: just configure URLs stream handler factory.

But we’ve outgrown the HttpURLConnection API. Its fully-synchronous API means that application code needs to manage how requests are dispatched. Requests and responses are together in one class which makes certain operations awkward or inefficient. Most painfully, we’re limited in what we can expose: Was my request redirected? Did the response come from a cache? OkHttp knows the answers to these questions but the HttpURLConnection API offers no way for you to ask them.

Request, Response, and Call

With 2.0, OkHttp introduces three fundamental types: RequestResponse, and Call. A call executes a request to produce a response. You can do that synchronously with a blocking call:

private final OkHttpClient client = new OkHttpClient();

public void run() throws Exception {
  Request request = new Request.Builder()
      .url("http://publicobject.com/helloworld.txt")
      .build();

  Call call = client.newCall(request);
  Response response = call.execute();

  if (!response.isSuccessful()) {
    throw new IOException("Unexpected code " + response);
  }
  System.out.println(response.body().string());
}

Or asynchronously with a callback:

Request request = new Request.Builder()
    .url("http://publicobject.com/helloworld.txt")
    .build();

Call call = client.newCall(request);
call.enqueue(new Callback() {
  @Override public void onFailure(Request request, IOException e) {
    logger.log(Level.SEVERE, "Failed to execute " + request, e);
  }

  @Override public void onResponse(Response response) throws IOException {
    if (!response.isSuccessful()) {
      throw new IOException("Unexpected code " + response);
    }
    System.out.println(response.body().string());
  }
});

A Request’s Journey

Above we complained that HttpURLConnection lacks APIs to ask how a response was reached. With redirects and caching, that journey can be interesting! One handy example is what happens when OkHttp downloads its own jar file from Maven Central.

Following Redirects

First we’re redirected from the HTTP to the HTTPS site:

> GET http://repository.sonatype.org/.../redirect?a=okhttp&v=LATEST

< 301 Moved Permanently
< Location: https://repository.sonatype.org/.../redirect?a=okhttp&v=LATEST

Next we’re redirected from the LATEST tag to the specific file we want.

> GET https://repository.sonatype.org/.../redirect?a=okhttp&v=LATEST

< 307 Temporary Redirect
< Location: https://repository.sonatype.org/.../content/.../okhttp-2.0.0.jar

Finally we download the file. The response includes headers to make caching possible.

> GET https://repository.sonatype.org/.../content/.../okhttp-2.0.0.jar

< 200 OK
< Last-Modified: Sat, 21 Jun 2014 01:00:00 GMT
< ETag: "{SHA1{4c8d1536dba3812cc1592090dc20c47a4ed3c35e}}"

OkHttp exposes these redirects with Response.priorResponse(). If you’re redirected multiple times, you will have a chain of prior responses. These will be returned in order from last-to-first; reverse them for chronological order:

List<Response> chainedResponses = new ArrayList<>();
for (Response r = response; r != null; r = r.priorResponse()) {
  chainedResponses.add(r);
}
Collections.reverse(chainedResponses);

for (Response r : chainedResponses) {
  System.out.println(r.request().url());
}
Cache and Network Responses

If we re-download the same URL, OkHttp’s response cache may kick inResponse offers two methods to check where a response came from: cacheResponse() and networkResponse(). Note that for conditional gets, both will be present!

When downloading a jar file from Maven Central, Response.cacheResponse() returns the cached response from above:

> GET https://repository.sonatype.org/.../content/.../okhttp-2.0.0.jar

< 200 OK
< Last-Modified: Sat, 21 Jun 2014 01:00:00 GMT
< ETag: "{SHA1{4c8d1536dba3812cc1592090dc20c47a4ed3c35e}}"

This cached response required validation from the server. OkHttp needed to ask, “Has the cached value changed?” Checking Response.networkResponse() confirms that it had not:

> GET https://repository.sonatype.org/.../content/.../okhttp-2.0.0.jar
> If-Modified-Since: Sat, 21 Jun 2014 01:00:00 GMT
> If-None-Match: "{SHA1{4c8d1536dba3812cc1592090dc20c47a4ed3c35e}}"

< 304 Not Modified

Prior responses from redirects also support cacheResponse() and networkResponse(). Use this to interrogate whether any part of a response used the network.

Upgrading to OkHttp 2.0

OkHttp 2.0 is not backwards-compatible. The changelog describes what’s changed and what’s gone. For example, to continue using the HttpURLConnection API, you will need the optionalokhttp-urlconnection dependency. To make upgrading easier, we’ve also released OkHttp 1.6 which is the 1.5 code plus some new 2.0 APIs. Use 1.6 to transition to 2.x APIs.

Get OkHttp from Maven or download it from the project website. Read more code examples in the project’s Recipes doc.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值