美文网首页
记:学习Okhttp源码

记:学习Okhttp源码

作者: 爱吃板栗的小女孩 | 来源:发表于2018-12-07 11:14 被阅读23次

本篇文章更像是学习下面这篇OKhttp后的读书笔记,看不懂我的请去看下面这篇文章
学习自,讲的特别好。需要仔细学习我觉得可以看一遍会收获很大:https://blog.piasy.com/2016/07/11/Understand-OkHttp/

在开始看这篇笔记之前,我强烈推荐你学习

https://www.jianshu.com/p/51a61845e66a
生动举例讲述Http的全过程,到底为什么Tcp是3次握手


知识点1.创建client
OkHttpClient okHttpClient=new OkHttpClient();

创建过程使用了builder建造者模式。建造者需要很多赋值,但是这里为什么会这么短一句话就可以呢?因为构造方法中写入了许多默认值(当然你也可以更改),当然可以看到默认的请求方式是Get请求


知识点2.发起http的请求
okHttpClient.newCall(request)
@Override public Call newCall(Request request) {
   return RealCall.newRealCall(this, request, false /* for web socket */);
}

调用okHttpClient.newCall()返回的是RealCall,进入发现方法前面有@Override,证明不是继承就是接口实现。最上方可看到是实现 Call.Factory ,产生的newCall()。由以上可知RealCall才是真正的请求执行者


知识点3.同步网络请求
//同步请求的方法
Response response=okHttpClient.newCall(request).execute();
同步请求部分.png
(1)Dispatcher:分发器,在同步网络请求中,只是用来告知执行到了哪一步: client.dispatcher().executed(this);开始执行; client.dispatcher().finished(this);执行结束
(2)网络请求的结果是Response result = getResponseWithInterceptorChain();,所以我们重点需要看这个地方。进入getResponseWithInterceptorChain()
  Response getResponseWithInterceptorChain() throws IOException {
    // Build a full stack of interceptors.
    List<Interceptor> interceptors = new ArrayList<>();
    interceptors.addAll(client.interceptors());
    interceptors.add(retryAndFollowUpInterceptor);
    interceptors.add(new BridgeInterceptor(client.cookieJar()));
    interceptors.add(new CacheInterceptor(client.internalCache()));
    interceptors.add(new ConnectInterceptor(client));
    if (!forWebSocket) {
      interceptors.addAll(client.networkInterceptors());
    }
    interceptors.add(new CallServerInterceptor(forWebSocket));

    Interceptor.Chain chain = new RealInterceptorChain(interceptors, null, null, null, 0,
        originalRequest, this, eventListener, client.connectTimeoutMillis(),
        client.readTimeoutMillis(), client.writeTimeoutMillis());

    return chain.proceed(originalRequest);
  }

a.从整体上来说,是有顺序的,是从上至下,依次执行。最后的intercepter一定是CallServerInterceptor,用于和服务器实际通讯。由于此过程有顺序,所以前面的拦截器一定会执行重定向缓存等一系列操作
b.所有interceptor(拦截器)意义:
client.interceptors():初始化OKhttpclient添加的
RetryAndFollowUpInterceptor:负责失败重试和重定向
BridgeInterceptor:负责把用户构造的请求转换为发送到服务器的请求、把服务器返回的响应转换为用户友好的响应的
CacheInterceptor:负责读取缓存直接返回、更新缓存
ConnectInterceptor:负责和服务器建立连接
NetworkInterceptors:配置 OkHttpClient时候设置的
CallServerInterceptor:负责向服务器发送请求数据、从服务器读取响应数据
c.下面直接引用文章的内容:责任链模式

zrl.png
d.intercepter也是一种分层模式:每一个intercepter只需要关注自己的责任,各层之间通过约定的接口/协议进行合作
知识点4.异步网络请求
//发起异步请求的方法
Call call=okHttpClient.newCall(request);
  call.enqueue(new Callback() {
      @Override
        public void onFailure(Call call, IOException e) {

        }

       @Override
        public void onResponse(Call call, Response response) throws IOException {

        }
});
//RealCall-enqueue
  @Override public void enqueue(Callback responseCallback) {
    synchronized (this) {
      if (executed) throw new IllegalStateException("Already Executed");
      executed = true;
    }
    captureCallStackTrace();
    eventListener.callStart(this);
    client.dispatcher().enqueue(new AsyncCall(responseCallback));
  }
//Dispatcher-enqueue
  synchronized void enqueue(AsyncCall call) {
    if (runningAsyncCalls.size() < maxRequests && runningCallsForHost(call) < maxRequestsPerHost) {
      runningAsyncCalls.add(call);
      executorService().execute(call);
    } else {
      readyAsyncCalls.add(call);
    }
  }

(1)Dispatcher:分发器:在异步网络请求中,如果当前还能执行一个并发请求,那就立即执行,否则加入 readyAsyncCalls 队列,而正在执行的请求执行完毕之后,会调用 promoteCalls() 函数,来把 readyAsyncCalls 队列中的 AsyncCall “提升”为 runningAsyncCalls,并开始执行。调度器主要维护两个线程队列(异步缓存队列,异步执行队列 ),每当异步执行队列中的请求执行完成后,就会从异步缓存队列中抽取请求过来到异步线程池中执行,形成一个异步循环


总结:

全流程图.png
1.OkHttpClient实现 Call.Factory,负责为 Request 创建 Call;
2.RealCall为真正发起请求的
3.Dispatcher在同步请求仅用于高知当前状态,在异步请求利用ExecutorService 实现,最终进行网络请求时和同步 execute() 接口一致,都是通过 getResponseWithInterceptorChain() 函数实现
4.getResponseWithInterceptorChain()采用了责任链模式,每个拦截器依次处理,处理不了的就交付给下一个拦截器继续处理

相关文章

网友评论

      本文标题:记:学习Okhttp源码

      本文链接:https://www.haomeiwen.com/subject/hmmocqtx.html