OkHttp

从使用开始

同步Get

OkHttpClient client = new OkHttpClient();
String run(String url) throws IOException {
    Request request = newRequest.Builder().url(url).build();
    Response response = client.newCall(request).execute();
    if (response.isSuccessful()) { 
        return response.body().string();
    } else { 
        throw new IOException("Unexpected code " + response);
    }
}

异步Get

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

Post

Post json

public static final MediaType JSON = MediaType.parse("application/json; charset=utf-8");
OkHttpClient client = new OkHttpClient();
String post(String url, String json) throws IOException {
    RequestBody body = RequestBody.create(JSON, json);
    Request request = new Request.Builder().url(url).post(body).build();
    Response response = client.newCall(request).execute();
    if (response.isSuccessful()) {
        return response.body().string();
    } else {
        throw new IOException("Unexpected code " + response);
    }
}

Post 键值对/表单

OkHttpClient client = new OkHttpClient();
String post(String url, String json) throws IOException {
    RequestBody formBody = new FormEncodingBuilder()
        .add("platform", "android")
        .add("name", "bug")
        .add("subject", "XXXXXXXXXXXXXXX")
        .build();
    Request request = new Request.Builder()
        .url(url)
        .post(body)
        .build();
    Response response = client.newCall(request).execute();
    if (response.isSuccessful()) {
        return response.body().string();
    } else {
        throw new IOException("Unexpected code " + response);
    }
}

Post流方式

以流的方式POST提交请求体。请求体的内容由流写入产生。

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\n");
            sink.writeUtf8("-------\n");
            for (int i = 2; i <= 997; i++) {
                sink.writeUtf8(String.format(" * %s = %s\n", 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());

}

Post 文件

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

Post 分块请求

MultipartBuilder可以构建复杂的请求体,与HTML文件上传形式兼容。多块请求体中每块请求都是一个请求体,可以定义自己的请求头。这些请求头可以用来描述这块请求。

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 {
    RequestBody requestBody = new MultipartBuilder()
        .type(MultipartBuilder.FORM)
        .addPart(
            Headers.of("Content-Disposition", "form-data;name=\"title\""),
            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());
}

取消Call

使用Call.cancel()可以立即停止掉一个正在执行的call。如果一个线程正在写请求或者读响应,将会引发IOException。当call没有必要的时候,使用这个api可以节约网络资源。

可以通过tags来同时取消多个请求。当你构建一请求时,使用RequestBuilder.tag(tag)来分配一个标签。之后你就可以用OkHttpClient.cancel(tag)来取消所有带有这个tag的call。

超时配置

没有响应时使用超时结束call。没有响应的原因可能是客户点链接问题、服务器可用性问题或者这之间的其他东西。OkHttp支持连接,读取和写入超时。

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

public void run() throws Exception {
    Request request = new Request.Builder()
        .url("http://httpbin.org/delay/2")
        .build();
    Response response = client.newCall(request).execute();
    System.out.println("Response completed: " + response);
}

每个Call的配置

使用OkHttpClient,所有的HTTP Client配置包括代理设置、超时设置、缓存设置。当你需要为单个call改变配置的时候,clone 一个 OkHttpClient。这个api将会返回一个浅拷贝(shallow copy),你可以用来单独自定义。

private final OkHttpClient client = new OkHttpClient();
public void run() throws Exception {
    Request request = new Request.Builder()
        .url("http://httpbin.org/delay/1") 
        .build();
    try {
        Response response = client.clone()
            .setReadTimeout(500, TimeUnit.MILLISECONDS)
            .newCall(request)
            .execute();
        System.out.println("Response 1 succeeded: " + response);
    } catch (IOException e) {
        System.out.println("Response 1 failed: " + e);
    }

    try {
        Response response = client.clone()
            .setReadTimeout(3000, TimeUnit.MILLISECONDS)
            .newCall(request)
            .execute();
        System.out.println("Response 2 succeeded: " + response);
    } catch (IOException e) {
        System.out.println("Response 2 failed: " + e);
    }
}

处理认证

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

}

results matching ""

    No results matching ""