Android 網絡框架OKHttp學習

jopen 9年前發布 | 15K 次閱讀 Android開發 移動開發 OkHttp

OKHTTP

okHttp: OKHttp是Android版Http客戶端。非常高效,支持SPDY、連接池、GZIP和 HTTP 緩存。默認情況下,OKHttp會自動處理常見的網絡問題,像二次連接、SSL的握手問題。如果你的應用程序中集成了OKHttp,Retrofit默認會使用OKHttp處理其他網絡層請求。
An HTTP & SPDY client for Android and Java applications 從Android4.4開始HttpURLConnection的底層實現采用的是okHttp.
使用要求:對于Android:2.3以上,對于Java:java7以上 兩個模塊: okhttp-urlconnection實現.HttpURLConnection API; okhttp-apache實現Apache HttpClient API. 依賴:okio(https://github.com/square/okio): Okio, which OkHttp uses for fast I/O and resizable buffers.

安裝:

maven:
com.squareup.okhttpokhttp2.3.0
Gradle:
compile 'com.squareup.okhttp:okhttp:2.3.0'

GET A URL

同步GET:

  private final OkHttpClient client = new OkHttpClient();

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

Response response = client.newCall(request).execute();
if (!response.isSuccessful()) throw new IOException(Unexpected code  + response);

Headers responseHeaders = response.headers();
for (int i = 0; i < responseHeaders.size(); i++) {
  System.out.println(responseHeaders.name(i) + :  + responseHeaders.value(i));
}

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

}</pre>

異步GET:

在一個工作線程中下載文件,當響應可讀時回調Callback接口。讀取響應時會阻塞當前線程。OkHttp現階段不提供異步api來接收響應體。
  private final OkHttpClient client = new OkHttpClient();

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

client.newCall(request).enqueue(new Callback() {
  @Override public void onFailure(Request request, Throwable throwable) {
    throwable.printStackTrace();
  }

  @Override public void onResponse(Response response) throws IOException {
    if (!response.isSuccessful()) throw new IOException(Unexpected code  + response);

    Headers responseHeaders = response.headers();
    for (int i = 0; i < responseHeaders.size(); i++) {
      System.out.println(responseHeaders.name(i) + :  + responseHeaders.value(i));
    }

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

}</pre>

訪問Header:

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

System.out.println(Server:  + response.header(Server));
System.out.println(Date:  + response.header(Date));
System.out.println(Vary:  + response.headers(Vary));

}</pre>

POST TO A SERVER

Posting a String:

public static final MediaType jsonReq
    = MediaType.parse(application/json; charset=utf-8);

OkHttpClient client = new OkHttpClient();

String post(String url, String json) throws IOException { RequestBody body = RequestBody.create(jsonReq, json); Request request = new Request.Builder() .url(url) .post(body) .build(); Response response = client.newCall(request).execute(); return response.body().string(); }</pre>

Posting Streaming:

 public static final MediaType MEDIA_TYPE_MARKDOWN
      = MediaType.parse(text/x-markdown; charset=utf-8);

private final OkHttpClient client = new OkHttpClient();

public void run() throws Exception { RequestBody requestBody = new RequestBody() { @Override public MediaType contentType() { return MEDIA_TYPE_MARKDOWN; }

  @Override public void writeTo(BufferedSink sink) throws IOException {
    sink.writeUtf8(Numbers

); sink.writeUtf8(------- ); for (int i = 2; i <= 997; i++) { sink.writeUtf8(String.format( * %s = %s , i, factor(i))); } }

  private String factor(int n) {
    for (int i = 2; i < n; i++) {
      int x = n / i;
      if (x * i == n) return factor(x) +  ×  + i;
    }
    return Integer.toString(n);
  }
};

Request request = new Request.Builder()
    .url(https://api.github.com/markdown/raw)
    .post(requestBody)
    .build();

Response response = client.newCall(request).execute();
if (!response.isSuccessful()) throw new IOException(Unexpected code  + response);

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

}</pre>

Posting a File:

 public static final MediaType MEDIA_TYPE_MARKDOWN
      = MediaType.parse(text/x-markdown; charset=utf-8);

private final OkHttpClient client = new OkHttpClient();

public void run() throws Exception { File file = new File(README.md);

Request request = new Request.Builder()
    .url(https://api.github.com/markdown/raw)
    .post(RequestBody.create(MEDIA_TYPE_MARKDOWN, file))
    .build();

Response response = client.newCall(request).execute();
if (!response.isSuccessful()) throw new IOException(Unexpected code  + response);

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

}</pre>

Posting from parameters:

private final OkHttpClient client = new OkHttpClient();

public void run() throws Exception { RequestBody formBody = new FormEncodingBuilder() .add(search, Jurassic Park) .build(); Request request = new Request.Builder() .url(https://en.wikipedia.org/w/index.php) .post(formBody) .build();

Response response = client.newCall(request).execute();
if (!response.isSuccessful()) throw new IOException(Unexpected code  + response);

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

}</pre>

Posting a multipart request:

 private static final String IMGUR_CLIENT_ID = ...;
  private static final MediaType MEDIA_TYPE_PNG = MediaType.parse(image/png);

private final OkHttpClient client = new OkHttpClient();

public void run() throws Exception { // Use the imgur image upload API as documented at https://api.imgur.com/endpoints/image RequestBody requestBody = new MultipartBuilder() .type(MultipartBuilder.FORM) .addPart( Headers.of(Content-Disposition, form-data; name= itle), RequestBody.create(null, Square Logo)) .addPart( Headers.of(Content-Disposition, form-data; name=image), RequestBody.create(MEDIA_TYPE_PNG, new File(website/static/logo-square.png))) .build();

Request request = new Request.Builder()
    .header(Authorization, Client-ID  + IMGUR_CLIENT_ID)
    .url(https://api.imgur.com/3/image)
    .post(requestBody)
    .build();

Response response = client.newCall(request).execute();
if (!response.isSuccessful()) throw new IOException(Unexpected code  + response);

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

}</pre>

Posing Json with Gson

 private final OkHttpClient client = new OkHttpClient();
  private final Gson gson = new Gson();

public void run() throws Exception { Request request = new Request.Builder() .url(https://api.github.com/gists/c2a7c39532239ff261be) .build(); Response response = client.newCall(request).execute(); if (!response.isSuccessful()) throw new IOException(Unexpected code + response);

Gist gist = gson.fromJson(response.body().charStream(), Gist.class);
for (Map.Entry<STRING, gistfile=""> entry : gist.files.entrySet()) {
  System.out.println(entry.getKey());
  System.out.println(entry.getValue().content);
}

}

static class Gist { Map<STRING, gistfile=""> files; }

static class GistFile { String content; }</STRING,></STRING,></pre>

Response Caching:

為了緩存響應,你需要一個你可以讀寫的緩存目錄,和緩存大小的限制。這個緩存目錄應該是私有的,不信任的程序應不能讀取緩存內容。
一個緩存目錄同時擁有多個緩存訪問是錯誤的。大多數程序只需要調用一次 new OkHttp() ,在第一次調用時配置好緩存,然后其他地方只需要調用這個實例就可以了。否則兩個緩存示例互相干擾,破壞響應緩存,而且有可能會導致程序崩潰。
響應緩存使用HTTP頭作為配置。你可以在請求頭中添加 Cache-Control: max-stale=3600 ,OkHttp緩存會支持。你的服務通過響應頭確定響應緩存多長時間,例如使用 Cache-Control: max-age=9600 。

private final OkHttpClient client;

public CacheResponse(File cacheDirectory) throws Exception { int cacheSize = 10 1024 1024; // 10 MiB Cache cache = new Cache(cacheDirectory, cacheSize);

client = new OkHttpClient();
client.setCache(cache);

}

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

Response response1 = client.newCall(request).execute();
if (!response1.isSuccessful()) throw new IOException(Unexpected code  + response1);

String response1Body = response1.body().string();
System.out.println(Response 1 response:           + response1);
System.out.println(Response 1 cache response:     + response1.cacheResponse());
System.out.println(Response 1 network response:   + response1.networkResponse());

}</pre>

Canceling a Call

    final Call call = client.newCall(request);
        call.cancel();

Timeouts:

private final OkHttpClient client;

public ConfigureTimeouts() throws Exception { client = new OkHttpClient(); client.setConnectTimeout(10, TimeUnit.SECONDS); client.setWriteTimeout(10, TimeUnit.SECONDS); client.setReadTimeout(30, TimeUnit.SECONDS); }</pre>

Handling Authentication:

private final OkHttpClient client = new OkHttpClient();

public void run() throws Exception { client.setAuthenticator(new Authenticator() { @Override public Request authenticate(Proxy proxy, Response response) { System.out.println(Authenticating for response: + response); System.out.println(Challenges: + response.challenges()); String credential = Credentials.basic(jesse, password1); return response.request().newBuilder() .header(Authorization, credential) .build(); }

  @Override public Request authenticateProxy(Proxy proxy, Response response) {
    return null; // Null indicates no attempt to authenticate.
  }
});

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

Response response = client.newCall(request).execute();
if (!response.isSuccessful()) throw new IOException(Unexpected code  + response);

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

}</pre>為避免當驗證失敗時多次重試,我們可以通過返回null來放棄驗證:

 if (responseCount(response) >= 3) {
    return null; // If we've failed 3 times, give up.
  }
//添加以下方法
private int responseCount(Response response) {
    int result = 1;
    while ((response = response.priorResponse()) != null) {
      result++;
    }
    return result;
  }

Interceptors

class LoggingInterceptor implements Interceptor {
  @Override public Response intercept(Chain chain) throws IOException {
    Request request = chain.request();

long t1 = System.nanoTime();
logger.info(String.format(Sending request %s on %s%n%s,
    request.url(), chain.connection(), request.headers()));

Response response = chain.proceed(request);

long t2 = System.nanoTime();
logger.info(String.format(Received response for %s in %.1fms%n%s,
    response.request().url(), (t2 - t1) / 1e6d, response.headers()));

return response;

} }</pre>

Application Interceptors:

OkHttpClient client = new OkHttpClient();
client.interceptors().add(new LoggingInterceptor());

Network Interceptors

OkHttpClient client = new OkHttpClient();
client.networkInterceptors().add(new LoggingInterceptor());

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!