ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

okhttp3.9.1源码初探

2021-01-27 10:01:00  阅读:148  来源: 互联网

标签:调用 拦截器 interceptors okhttp3.9 client 初探 new RealCall 源码


okhttp3.9.1源码初探

  1. 简单调用方式
  • get同步调用调用
public class GetExample {
//1.创建OkHttpClient对象
  OkHttpClient client = new OkHttpClient();

  String run(String url) throws IOException {
  //2.通过Builder建造者模式创建Request对象
    Request request = new Request.Builder()
        .url(url)
        .build();
	//3.通过client.newCall(request)方法传入Request对象得到Call对象,调用execute()方法同步获取请求结果Response
    try (Response response = client.newCall(request).execute()) {
      return response.body().string();
    }
  }

  public static void main(String[] args) throws IOException {
    GetExample example = new GetExample();
    String response = example.run("https://raw.github.com/square/okhttp/master/README.md");
    System.out.println(response);
  }
}

  • get异步调用
    就是获取Call对象之后调用enqueue(Callback)方法传入Callback回调,获取请求结果Response
  1. 同步调用流程
    client对象和request对象创建之后client会调用newCall方法获取Call对象,代码如下
  /**
   * Prepares the {@code request} to be executed at some point in the future.
   */
  @Override public Call newCall(Request request) {
    return RealCall.newRealCall(this, request, false /* for web socket */);
  }

如上,在okhttpclient类中,调用newCall方法会执行

RealCall.newRealCall(this, request, false /* for web socket */);

方法
查看RealCall类中该方法如下

  static RealCall newRealCall(OkHttpClient client, Request originalRequest, boolean forWebSocket) {
    // Safely publish the Call instance to the EventListener.
    RealCall call = new RealCall(client, originalRequest, forWebSocket);
    call.eventListener = client.eventListenerFactory().create(call);
    return call;
  }

如上,在该方法中常见了RealCall对象并返回
RealCall的构造方法如下

  private RealCall(OkHttpClient client, Request originalRequest, boolean forWebSocket) {
    this.client = client;
    this.originalRequest = originalRequest;
    this.forWebSocket = forWebSocket;
    this.retryAndFollowUpInterceptor = new RetryAndFollowUpInterceptor(client, forWebSocket);
  }

如上,在RealCall方法中保存了传入的参数,并创建了RetryAndFollowUpInterceptor,重定向拦截器。

接着RealCall调用了excute()方法

  @Override public Response execute() throws IOException {
    synchronized (this) {
      if (executed) throw new IllegalStateException("Already Executed");
      executed = true;
    }
    captureCallStackTrace();
    eventListener.callStart(this);
    try {
    //关注点1.通过client调用dispacher()方法获取Dispacher对象,并调用其executed方法
      client.dispatcher().executed(this);
      //关注点2.调用getResponseWithInterceptorChain();方法
      Response result = getResponseWithInterceptorChain();
      if (result == null) throw new IOException("Canceled");
      return result;
    } catch (IOException e) {
      eventListener.callFailed(this, e);
      throw e;
    } finally {
      client.dispatcher().finished(this);
    }
  }

关注点1:client如何通过dispacher()方法获取Dispacher对象的,查看client的dispacher()方法如下

  public Dispatcher dispatcher() {
    return dispatcher;
  }

直接返回了dispacher对象,那它在何时创建的,通过查看源码发现okhttpclient也是通过Builder模式创建的,其内部类Builder在构造方法中创建了Dispacher对象,代码如下:

   public Builder() {
   //在这里创建了dispacher对象
      dispatcher = new Dispatcher();
      protocols = DEFAULT_PROTOCOLS;
      connectionSpecs = DEFAULT_CONNECTION_SPECS;
      eventListenerFactory = EventListener.factory(EventListener.NONE);
      proxySelector = ProxySelector.getDefault();
      cookieJar = CookieJar.NO_COOKIES;
      socketFactory = SocketFactory.getDefault();
      hostnameVerifier = OkHostnameVerifier.INSTANCE;
      certificatePinner = CertificatePinner.DEFAULT;
      proxyAuthenticator = Authenticator.NONE;
      authenticator = Authenticator.NONE;
      connectionPool = new ConnectionPool();
      dns = Dns.SYSTEM;
      followSslRedirects = true;
      followRedirects = true;
      retryOnConnectionFailure = true;
      connectTimeout = 10_000;
      readTimeout = 10_000;
      writeTimeout = 10_000;
      pingInterval = 0;
    }

然后调用dispacher的excute()方法,代码如下:

  /** Used by {@code Call#execute} to signal it is in-flight. */
  synchronized void executed(RealCall call) {
  //发现只是加入了runningSyncCall队列
    runningSyncCalls.add(call);
  }

Dispacher对象初始化时创建了三个队列用来存放call

  /** Ready async calls in the order they'll be run. 准备异步执行的Call队列*/
  private final Deque<AsyncCall> readyAsyncCalls = new ArrayDeque<>();

  /** Running asynchronous calls. Includes canceled calls that haven't finished yet.正在执行的异步Call队列 */
  private final Deque<AsyncCall> runningAsyncCalls = new ArrayDeque<>();

  /** Running synchronous calls. Includes canceled calls that haven't finished yet. 正在异性的同步Call队列*/
  private final Deque<RealCall> runningSyncCalls = new ArrayDeque<>();

然后看关注点2:调用getResponseWithInterceptorChain();方法,方法如下:

  Response getResponseWithInterceptorChain() throws IOException {
    // Build a full stack of interceptors.
    //1.创建了一个存放拦截器的数组
    List<Interceptor> interceptors = new ArrayList<>();
    //2.将okhttpclient中设置的拦截器添加到数组中
    interceptors.addAll(client.interceptors());
    //3.添加重定向拦截器
    interceptors.add(retryAndFollowUpInterceptor);
    //4.添加桥接拦截器,主要用来构造请求参数及请求结果
    interceptors.add(new BridgeInterceptor(client.cookieJar()));
    //5.添加缓存拦截器
    interceptors.add(new CacheInterceptor(client.internalCache()));
    //6.添加链接拦截器
    interceptors.add(new ConnectInterceptor(client));
    if (!forWebSocket) {
    //7.添加网络拦截器
      interceptors.addAll(client.networkInterceptors());
    }
    //8.添加访问拦截器
    interceptors.add(new CallServerInterceptor(forWebSocket));
	//9.创建RealInterceptorChain对象
    Interceptor.Chain chain = new RealInterceptorChain(interceptors, null, null, null, 0,
        originalRequest, this, eventListener, client.connectTimeoutMillis(),
        client.readTimeoutMillis(), client.writeTimeoutMillis());
	//10.调用procceed()方法执行
    return chain.proceed(originalRequest);
  }

接下来就是各种拦截器的相关知识,okHttp采用责任链模式来处理请求和请求结果,从上到下依次是
retryAndFollowUpInterceptor,BridgeInterceptor,CacheInterceptor,ConnectInterceptor,CallServerInterceptor。

标签:调用,拦截器,interceptors,okhttp3.9,client,初探,new,RealCall,源码
来源: https://blog.csdn.net/TianDevelopers/article/details/113183924

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有