美文网首页
okhttp的源码分析

okhttp的源码分析

作者: Neo_NeverAfraid | 来源:发表于2022-07-14 16:32 被阅读0次

    几个关键的类: intercept接口,RealInterceptorChain责任链,RealCall 发起请求,CallServerInterceptor真正请求网络的类

    先看看 okhttp 的请求流程

    1. 创建 请求对象Call
      @Override public Call newCall(Request request) {
        return RealCall.newRealCall(this, request, false );
      }
    
    1. 调用execute 执行请求 并 返回 Response对象
      @Override protected void execute() {
            Response response = getResponseWithInterceptorChain();
        }
    

    以上只展示最关键的代码, execute() 通过getResponseWithInterceptorChain方法获得Response 返回结果. 让我们看看这个方法里做了什么事情.

    1. 添加拦截器 并调用 chain.proceed 方法
      Response getResponseWithInterceptorChain() throws IOException {
        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);
      }
    

    这里需要说明一下,首先会创建一个interceptors的集合,这里包含了所有的拦截器,包括开发者自定义的拦截器以及okhttp自带的五大拦截器.注意添加的顺序,自定义拦截器会首先被加入到集合中,然后才是系统自带的拦截器.最后一个拦截器是CallServerInterceptor,它是真正处理网络请求的拦截器.
    接下来会创建Interceptor.Chain对象,把添加后的拦截器集合,原始请求,监听器,配置属性作为参数,传入到Chain对象中.
    最后执行chain.proceed(originalRequest).

    4.核心方法 chain.proceed

    public Response proceed(Request request, StreamAllocation streamAllocation, HttpCodec httpCodec,
          RealConnection connection) throws IOException {
     RealInterceptorChain next = new RealInterceptorChain(interceptors, streamAllocation, httpCodec,
            connection, index + 1, request, call, eventListener, connectTimeout, readTimeout,
            writeTimeout);
        Interceptor interceptor = interceptors.get(index);
        Response response = interceptor.intercept(next);
    }
    

    这是最核心的方法, index表示当前方法拦截器的在拦截器集合中的下标, interceptors会取出集合的下个拦截器,并调用它的intercept方法.

     Interceptor interceptor = interceptors.get(index);
     Response response = interceptor.intercept(next);
    

    以上两句代码是okhttp责任链模式的本质. intercept方法会调用的chain.proceed,chain.proceed又调用责任链中的下一个拦截器的intercept方法.这是一个递归的调用.

    1. interceptor.intercept(Chain chain)
    public class HeaderParamInterceptor implements Interceptor {
        @Override
        public Response intercept(Chain chain) throws IOException {
            Request request = chain.request();
            Request.Builder builder = request.newBuilder();
            builder.addHeader("token", TokenInvalidInterceptor.getToken());
            builder.addHeader("clientId", "12345678");
            builder.addHeader("requestId", UUID.randomUUID().toString().replace("-", "").toLowerCase());
            return chain.proceed(builder.build());
        }
    
    }
    

    以自定义HeaderParamInterceptor为例,在方法里先执行业务操作,比如这是给request请求添加header公共参数,最后执行chain.proceed方法,根据我们之前的分析,request请求会交给拦截器集合中的下一个拦截器处理.这个取决我们添加拦截器的顺序.最后一个拦截器是真正请求网络的拦截器.

    6.CallServerInterceptor

    public final class CallServerInterceptor implements Interceptor {
    
      @Override public Response intercept(Chain chain) throws IOException {
    
     RealInterceptorChain realChain = (RealInterceptorChain) chain;
        HttpCodec httpCodec = realChain.httpStream();
        StreamAllocation streamAllocation = realChain.streamAllocation();
        RealConnection connection = (RealConnection) realChain.connection();
        Request request = realChain.request();
    
        long sentRequestMillis = System.currentTimeMillis();
    
        realChain.eventListener().requestHeadersStart(realChain.call());
        httpCodec.writeRequestHeaders(request);
        realChain.eventListener().requestHeadersEnd(realChain.call(), request);
        ... 省略一部分逻辑 ...
        request.body().writeTo(bufferedRequestBody);
        Response response = responseBuilder
            .request(request)
            .handshake(streamAllocation.connection().handshake())
            .sentRequestAtMillis(sentRequestMillis)
            .receivedResponseAtMillis(System.currentTimeMillis())
            .build();
        ... 省略一部分逻辑 ...
        return response;
    }
    
    

    毫无疑问,这是最后发起请求网络并得到服务器返回Reponse对象的地方,不用过多得纠结其内部的逻辑细节.可以很清晰地看出这里在做http请求的封装处理.并通过发起网络请求得到了最终的Response对象.我们可以确定这是一个发生在子线程的阻塞方法.
    其他的拦截器在Interceptor方法的最后一行返回chain.proceed(request),但是CallServerInterceptor是直接返回Response对象,这是递归的终点.
    然后每个拦截器按照拦截器集合添加的顺序,由后往前依次返回Reponse对象,我们对参数的处理也是在这个过程中,最典型的就是使用自定义拦截器,根据服务器返回的code的不同,来处理失效的token.

    bf4312555f43b9f224822884886458c.png

    最后,我们可以总结出以下的结论:
    一. 每个拦截器都有intercept方法,我们可以从RealCall的getResponseWithInterceptorChain方法里找到interceptors集合添加拦截器的顺序:

    1. 自定义拦截器
    2. okhttp四大拦截器(retryAndFollowUpInterceptor,BridgeInterceptor,CacheInterceptor,ConnectInterceptor),
    3. 如果有网络的情况下,会添加networkInterceptors
    4. 最后调用真正的请求网络的拦截器 CallServerInterceptor.

    二. 拦截器集合会被传入到RealInterceptorChain中去. 在proceed方法里,会执行

    Interceptor interceptor = interceptors.get(index);
    Response response = interceptor.intercept(next);
    

    每次调用chain.proceed, interceptors的index都会加一,这样Response response = interceptor.intercept(next) 就成为了递归调用,最后由CallServerInterceptor的intercept方法返回Response结果.

    三. 在任何一个拦截器的intercept方法中,修改Request请求参数都必须在chain.proceed之前操作,修改Reponse返回结果必须在chain.proceed方法之后操作.chain.proceed一旦有返回结果就代表网络请求结果返回了.

    相关文章

      网友评论

          本文标题:okhttp的源码分析

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