An HTTP & HTTP/2 client for Android and Java applications
引用自什么都不管,先上个代码。敲完再说。
GET
OkHttpClient client = new OkHttpClient(); Request request = new Request.Builder() .get() .url(PATH) .build(); client.newCall(request).enqueue(new Callback() { @Override public void onFailure(Call call, IOException e) { } @Override public void onResponse(Call call, Response response) throws IOException { if (response.isSuccessful()) { String string = response.body().string(); Log.i(TAG, "onResponse: "+string); } } });
上面的图中显示了response.body()
可以得到的数据类型。在上面的例子中我们使用了string()
来得到了相应的字符串数据。
POST
这是一个异步调用的例子。
MediaType jsonType = MediaType.parse("application/json; charset=utf-8"); OkHttpClient client = new OkHttpClient(); String jsonStr = new Gson().toJson(mPerson); RequestBody body = RequestBody.create(jsonType,jsonStr); Request request = new Request.Builder() .post(body) .url(PATH) .build(); client.newCall(request).enqueue(new Callback() { @Override public void onFailure(Call call, IOException e) { } @Override public void onResponse(Call call, Response response) throws IOException { if (response.isSuccessful()){ String string = response.body().string(); Log.i(TAG, "post: "+string); } } });
请求大致过程
我们每次做请求的时候都要有一个OkHttpClient
实体,用来构建我们的一次请求。而Request
类用来设置我们请求需要的参数,之后我们就可以通过client
来发送一个请求了。在上面的例子中,我们将请求加入到了一个请求队列中(enqueue)
。最后我们就得到了这次请求的响应response
了。
Request
在构建Request
的时候,使用到了Builder
设计模式。只需要简单的链式调用配置好请求参数。如下:
Request request = new Request.Builder().url(PATH) .header("User-Agent", "my-agent") .addHeader("Accept-Language", "zh-cn") .get() .build();
header && addHeader
header
和addHeader
用来添加头部字段的key-value
对。
/** * Sets the header named {@code name} to {@code value}. If this request already has any headers * with that name, they are all replaced. */ public Builder header(String name, String value) { headers.set(name, value); return this; } /** * Adds a header with {@code name} and {@code value}. Prefer this method for multiply-valued * headers like "Cookie". * *Note that for some headers including {@code Content-Length} and {@code Content-Encoding}, * OkHttp may replace {@code value} with a header derived from the request body. */ public Builder addHeader(String name, String value) { headers.add(name, value); return this; }
我们看到,这两个函数底层一个是使用的Header.Builder
的set()
,一个是使用的add()
.在继续往里看:
/** * Set a field with the specified value. If the field is not found, it is added. If the field is * found, the existing values are replaced. */ public Builder set(String name, String value) { checkNameAndValue(name, value); removeAll(name); addLenient(name, value); return this; } /** Add a field with the specified value. */ public Builder add(String name, String value) { checkNameAndValue(name, value); return addLenient(name, value); }
这就很清晰了。很明显了。set()
调用了removeAll(key)
方法来删除之前设置了同名的key。而add
并没有删除。其实从名字我们就可以看出来。add
就是添加嘛。set
设置,肯定只有一个嘛。
RequestBody
OkHttpClient client =new OkHttpClient(); MediaType parse = MediaType.parse("application/json; charset=utf-8"); RequestBody body = RequestBody.create(parse,new Gson().toJson(mPerson)); Request request = new Request.Builder().url(PATH) .header("User-Agent", "my-agent") .addHeader("Accept-Language", "zh-cn") .post(body) .build(); client.newCall(request).enqueue(new Callback() { @Override public void onFailure(Call call, IOException e) { } @Override public void onResponse(Call call, Response response) throws IOException { } });
将上面的请求通过抓包工具抓取后,下图即为本次的请求。
ResponseBody
是一个抽象类。在okhttp
中的子类有FormBody
和MultipartBody
。 我们可以通过静态方法create
来构建一个ResponseBody
。
ResponseBody
内部的create
可以通过三中方式构建。当然了。我们也可以模仿官方的crete
方法来构建自己的
ResponseBody
来上传制定类型的文件。我们通过MediaType
来指定我们上传文件的类型。比如上面代码中的"application/json; charset=utf-8"
就是我们上传的内容的类型。当我们有什么文件想要提交,但是不知道key
是什么的时候可以看MIME 参考手册 FormBody
用来提交一些表单数据。通过FormBody.Builder
来添加表单数据。如下所示:
OkHttpClient client = new OkHttpClient(); FormBody formBody = new FormBody.Builder() .add("username", "jason") .add("password", "magicer") .build(); Request request = new Request.Builder() .post(formBody) .addHeader("User-Agent", "Apple") .build(); Response response = client.newCall(request).execute();
在FromBody
中,查看其源码我们可以看到FormBody
设置的Content-Type
为"application/x-www-form-urlencoded"
.也就是普通表单数据。
private static final MediaType CONTENT_TYPE = MediaType.parse("application/x-www-form-urlencoded");
MultipartBody
以下是MultipartBody
中的一些个类型。
public static final MediaType MIXED = MediaType.parse("multipart/mixed");public static final MediaType ALTERNATIVE = MediaType.parse("multipart/alternative");public static final MediaType DIGEST = MediaType.parse("multipart/digest");public static final MediaType PARALLEL = MediaType.parse("multipart/parallel");public static final MediaType FORM = MediaType.parse("multipart/form-data");