what
非常好用的请求库,还是附上官方文档
how
正常步骤就是
- 构建键Client
- 添加header
- 拦截器
- 缓存
- dns
- 代理
- 超时
- 监听事件
- 构建请求Request
- url
- header
- 请求方式
- 请求体
- 发送请求Call
- 获得响应Response
- 处理响应
简单同步请求
1 | OkHttpClient client = new OkHttpClient(); |
简单异步请求
就是简单的将execute换成了enqueue传入回调,这是异步的哦,会切换线程。但是再Test测试方法中,需要让外面的线程等待下,不然是看不到的结果的。
1 | OkHttpClient client = new OkHttpClient(); |
发送Post请求
如果不对Request进行设置,默认就是get请求。
1 | RequestBody requestBody = new Request.Builder().addHeader().build(); |
所以主要就是看RequestBody的构建了
通过静态方法create进行构建
1 | MediaType contentType = MediaType.parse("text/x-markdown; charset=utf-8"); |
大概有这么几种:
1 | create(//字符串 MediaType contentType, String content); |
所以也可以直接构建提交文件RequestBody的。
实现RequestBody
1 | RequestBody requestBody1 = new RequestBody() { |
发送普通表单
RequestBody有一个实现类FormBody
1 | FormBody formBody = new FormBody.Builder() |
发送Multi表单
RequestBody另一个一个实现类MultipartBody,添加许多Part
1 | MultipartBody body = new MultipartBody.Builder() |
拦截器
OkHttp的核心可以就在于拦截器,内部通过拦截器链式调用。监听,重写,重试call
看下官网给的例子,用于测试请求消耗的时间
1 | class LoggingInterceptor implements Interceptor { |
拦截分为两种:
全局拦截器 通过
OkHttpClient.Builder#addInterceptor(Interceptor)
加入网络拦截器 通过
OkHttpClient.Builder#addNetworkInterceptor(Interceptor)
加入,真正发起网络请求调用
Application Interceptors
全局拦截器:
- 不用关心重连,重定向
- 总是调用一次,即使http响应是来自缓存。
- 可以观察原始请求意图,
- 允许短路,不调用
Chain.proceed()
- 允许多次调用
Chain.proceed()
一般我们可比如:从本地取出并注入cookie,以及取出cookie持久化到本地
1 | /** |
1 | /** |
Network Interceptors
- 能够操纵中间响应,重定向,重试
- 缓存中响应不会调用
- 可观察网络传输数据
- 可以获得具体Connection进行操作,比如IP,TLS等
代码分析
首先看下各个类的概念
- OkHttpClient 客户端:维持了线程池,避免重复创键消耗资源,最好使用复用一个
- Dispatcher 线程池抽象聚合:维护一个核心线程为了0,上限Int最大数,存活时间60s的线程池
- Response 请求的封装:包含了请求行,请求头,请求体
- Response 响应的封装:包含了状态码,响应头,响应体
- Call 一次请求的具体对象,分为同步和异步
- Interceptor 拦截器,拦截并处理,交下个拦截器
- Chain 请求链,和拦截器一起构成责任链模式
构建Client
Builder模式,构建client,有默认配置
1 | public OkHttpClient() { |
构建请求
同样Builder模式
1 | Request(Builder builder) { |
newCall
实例出RealCall
1 | public Call newCall(Request request) { |
同步请求
1 | public Response execute() throws IOException { |
call入队列
1 | synchronized void executed(RealCall call) { runningSyncCalls.add(call);} |
进行请求返回响应
1 | Response getResponseWithInterceptorChain() throws IOException { |
进入拦截器链
1 | public Response proceed(Request request, Transmitter transmitter, @Nullable Exchange exchange) |
经历重重拦截器,通过Okio库进行对Socket进行流的读写,就完成一次请求。
异步请求
和同步请求不一样,具体是AsyncCall,将请求提交给线程池,触发回调。
1 | public void enqueue(Callback responseCallback) { |
1 | void enqueue(AsyncCall call) { |
1 | private boolean promoteAndExecute() { |
AsnycCall是个Runaable实现
1 | void executeOn(ExecutorService executorService) { |
线程具体执行的地方
走到这里就和同步请求一致了
1 | protected void execute() { |
补充
- Response读取一次内容会关闭,所以只能读取一次
- Response读取byteStream时,需要手动close它
参考: