OkHttp3

前言

网络基础知识->socket原理、编程->httpUrlConnection->OkHttp->retrofit,循序渐进

框架图

okhttp框架图.png

简介(摘自官网)

HTTP是现代应用常用的一种交换数据和媒体的网络方式,高效地使用HTTP能让资源加载更快,节省带宽。OkHttp是一个高效的HTTP客户端,它有以下默认特性:

  • 支持HTTP/2,允许所有同一个主机地址的请求共享同一个socket连接
  • 连接池减少请求延时
  • 透明的GZIP压缩减少响应数据的大小
  • 缓存响应内容,避免一些完全重复的请求
  • 请求失败时自动重试主机的其他 IP,自动重定向
  • 当握手失败时会回退到TLS 1.0

PS:关于Http2.0,阿简认为该大V分析的很好,推荐参考:一文读懂 HTTP/2 特性
总结来说http2有相比于http1.x有以下几个特点:

  • HTTP / 1 的请求和响应报文,都是由起始行,首部和实体正文(可选)组成,各部分之间以文本换行符分隔。HTTP/2 将请求和响应数据分割为更小的帧,并且它们采用二进制编码。
  • 多路复用,代替原来的序列和阻塞机制。所有就是请求的都是通过一个 TCP连接并发完成。
  • 头部压缩(客户端服务端都建立首部表,每次请求响应只需要发送差异数据,客户端和服务器共同渐进地更新)

使用

  • okhttp采用建造者模式设计,使用很方便

GET异步请求

String url = "http://wwww.baidu.com";
//创建一个http客户端对象
OkHttpClient okHttpClient = new OkHttpClient();
final Request request = new Request.Builder()
        .url(url)
        .get()//默认就是GET请求,可以不写
        .build();
//发起异步请求
Call call = okHttpClient.newCall(request);
call.enqueue(new Callback() {
    @Override
    public void onFailure(Call call, IOException e) {
        Log.d(TAG, "onFailure: ");
    }

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

GET同步请求

String url = "http://wwww.baidu.com";
OkHttpClient okHttpClient = new OkHttpClient();
final Request request = new Request.Builder()
        .url(url)
        .build();
final Call call = okHttpClient.newCall(request);
new Thread(new Runnable() {
    @Override
    public void run() {
        try {
            Response response = call.execute();
            Log.d(TAG, "run: " + response.body().string());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}).start();

因为是GET请求,所以没有请求体,只需要请求头和请求行就可以,所以Request中只需要说明请求方法、URL即可(原理可参考:[网络基本知识-http]
(https://www.jianshu.com/p/291819f78a53))

POST方式提交String

使用HTTP POST的请求体发送到服务。下面例子post了一个markdown文档到一个的Web服务(将markdown作为HTML)。由于整个请求体是同时在内存中,应避免使用此API发送较大(大于1 MIB)的文件。

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 {
    String postBody = ""
        + "Releases\n"
        + "--------\n"
        + "\n"
        + " * _1.0_ May 6, 2013\n"
        + " * _1.1_ June 15, 2013\n"
        + " * _1.2_ August 11, 2013\n";

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

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

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

POST方式提交Streaming

在这里,我们POST请求体作为stream。正在生成请求体的内容写入到stream中。下面例子streams直接进入 Okio缓冲水槽。你的程序可能更喜欢使用OutputStream,你可以通过BufferedSink.outputStream()获得 OutputStream。

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

PS:通过以上POST的三种方式来看,因为post请求如果是提交数据的话一般都会使用到请求体,所以在okhttp中使用post的时候,主要的是两点:1.MediaType 协议 2.构建请求体RequestBody
关于请求报文有疑问的可以参考阿简的这篇文章:网络基本知识-http

拦截器

关于拦截器,阿简写了一篇很通俗易懂的文章方便大家理解:okhttp3拦截器源码逐行分析(okhttp-3.14.4)

END

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容