okhttp3使用详解

简介

OkHttp 是一个高效的 HTTP 客户端,具有非常多的优势:

  1. 能够高效的执行 http,数据加载速度更快,更省流量
  2. 支持 GZIP 压缩,提升速度,节省流量
  3. 缓存响应数据,避免了重复的网络请求
  4. 使用简单,支持同步阻塞调用和带回调的异步调用

OkHttp 支持 Android2.3 以上,JDK1.7 以上。

官网地址:https://square.github.io/okhttp/
github地址:https://github.com/square/okhttp

基本使用

引入依赖

在pom中添加下列代码

<!-- https://mvnrepository.com/artifact/com.squareup.okhttp3/okhttp -->
<dependency>
    <groupId>com.squareup.okhttp3</groupId>
    <artifactId>okhttp</artifactId>
    <version>4.9.0</version>
</dependency>

Get请求

使用 OkHttp 进行 Get 请求只需要四个步骤

  1. 新建 OkHttpClient对象
  2. 构造 Request 对象
  3. 将 Request 对象封装为 Call
  4. 通过 Call 来执行同步或异步请求
String URL = "https://www.hanzoy.com";
OkHttpClient Client = new OkHttpClient();
Request request = new Request.Builder()
    .url(URL)
    .get()//默认get请求,可以不写
    .build();
final Call call = Client.newCall(request);

同步请求

try {
    Response response = call.execute();
    Log.d(TAG, response.body().toString());
} catch (IOException e) {
    e.printStackTrace();
}

如果是使用安卓开发的话,由于这种方式会阻塞线程,而为了避免 ANR 异常,Android3.0 之后已经不允许在主线程中访问网络了,所以 OkHttp 的同步 get 请求需要开启一个子线程:

new Thread(new Runnable() {
    @Override
    public void run() {
        try {
            Response response = call.execute();
            Log.d(TAG, response.body().toString());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}).start();

异步请求

call.enqueue(new Callback() {
    @Override
    public void onFailure(Call call, IOException e) {
        Log.d(TAG, "onFailure: " + e);
    }

    @Override
    public void onResponse(Call call, Response response) throws IOException {
        Log.d(TAG, "OnResponse: " + response.body().toString());
    }
});

Post请求

创建Post的请求与Get方法类似,只需要在Request添加一个请求参数对象RequestBody ,用于携带我们需要提交的数据。

使用FormBody.Builder

String URL = "https://www.hanzoy.com";
OkHttpClient Client = new OkHttpClient();
FormBody body = new FormBody.Builder()
    .add("name", "hanzoy")
    .add("age", "19")
    .build();
Request request = new Request.Builder()
    .url(URL)
    .post(body)
    .build();
Call call = Client.newCall(request);

使用RequestBody.create
使用RequestBody.create()方法创建RequestBody需要添加Content-Type(MediaType)属性,即是Internet Media Type,互联网媒体类型;也叫做MIME类型,在Http协议消息头中,使用Content-Type来表示具体请求中的媒体类型信息。用于定义网络文件的类型和网页的编码,决定文件接收方将以什么形式、什么编码读取这个文件。常见的媒体格式类型有:

  • text/html:HTML格式
  • text/pain:纯文本格式
  • image/jpeg:jpg图片格式
  • application/json:JSON数据格式
  • application/octet-stream:二进制流数据(如常见的文件下载)
  • application/x-www-form-urlencoded:form表单encType属性的默认格式,表单数据将以key/value的形式发送到服务端
  • multipart/form-data:表单上传文件的格式

上传JSON字符串:

String URL = "https://www.hanzoy.com";
OkHttpClient Client = new OkHttpClient();
MediaType mediaType = MediaType.parse("application/json; charset=utf-8");
String jsonStr = "{\"name\":\"hanzoy\",\"age\":\"19\"}";
RequestBody body = RequestBody.create(jsonStr, mediaType);
Request request = new Request.Builder()
    .url(URL)
    .post(body)
    .build();
Call call = Client.newCall(request);

上传文件:

String URL = "https://www.hanzoy.com";
OkHttpClient Client = new OkHttpClient();
MediaType mediaType = MediaType.parse("application/octet-stream");
File file = new File(filePath);
RequestBody body = RequestBody.create(file, mediaType);
Request request = new Request.Builder()
    .url(URL)
    .post(body)
    .build();
Call call = Client.newCall(request);

使用MultipartBody同时上传多种类型数据

String URL = "https://www.hanzoy.com";
OkHttpClient Client = new OkHttpClient();
File file = new File(filePath);
MultipartBody multipartBody = new MultipartBody.Builder()
    .setType(MultipartBody.FORM)
    .addFormDataPart("name", "zhangsan")
    .addFormDataPart("age", "20")
    .addFormDataPart("file", file.getName(),
                     RequestBody.create(file, MediaType.parse("application/octet-stream")))
    .build();
Request request = new Request.Builder()
    .url(URL)
    .post(multipartBody)
    .build();
Call call = Client.newCall(request);

同步与异步请求

Post的同步异步请求与Get请求完全一样,参照上面Get的请求即可,这里就不多赘述。

其他应用场景

手动处理302跳转等重定向

OkHttpClient client = new OkHttpClient().newBuilder()
    .followRedirects(false)  //禁制OkHttp的重定向操作,我们自己处理重定向
    .build();

一个好奇的人