OkHttp (c) - interceptor chain analysis process

Previous analysis of the specific implementation process the request, the request will eventually go through a chain of multiple interceptors to handle specific requests and responses, this is what we call the well-known chain (Chain of Responsibility) mode

Chain of Responsibility pattern


Chain of Responsibility pattern (Chain of Responsibility Pattern) created a chain recipient object to the request. In order to avoid requesting sender process's are coupled together, all of the requests are processed by the preceding objects in mind that the next object reference into a chain connected to a plurality of requests; occurs when there is a request, the request can be along this chain transfer until it has processed so far objects. as the picture shows:

The figure vividly describes the behavior of the chain of responsibility pattern here is not specifically launched to introduce, For further information, refer to the relevant information.

Interceptor chain


In OkHttp, the chain of responsibility of a variety of processors interceptors, in addition to the core itself provides five interceptors, also allows a user to custom interceptor to intercept and chain added chain. Let's look at this "chain" interface definition:

  interface Chain {
    //返回请求对象
    Request request();
    //执行具体的请求,并获取响应
    Response proceed(Request request) throws IOException;
    //返回连接
    Connection connection();
  }
复制代码

Wherein the method is very important to proceed, which defines an input request, outputs the response, the specific implementation subclasses performed. RealInterceptorChain is a subclass of its implementation, which proceed to achieve the following method:

    @Override
    public Response proceed(Request request) throws IOException {
        return proceed(request, streamAllocation, httpCodec, connection);
    }
复制代码

Run interceptor chain

RealInterceptorChain proceed method invocation implemented proceed their method, this method is implemented interceptor chain model, which defines how we deal with our request interceptor through the layers, the process of obtaining the response, implementation details with reference to the following code :

    public Response proceed(Request request, StreamAllocation streamAllocation, HttpCodec httpCodec,
                            RealConnection connection) throws IOException {
        if (index >= interceptors.size()) throw new AssertionError();

        calls++;

        // If we already have a stream, confirm that the incoming request will use it.
        if (this.httpCodec != null && !this.connection.supportsUrl(request.url())) {
            throw new IllegalStateException("network interceptor " + interceptors.get(index - 1)
                    + " must retain the same host and port");
        }

        // If we already have a stream, confirm that this is the only call to chain.proceed().
        if (this.httpCodec != null && calls > 1) {
            throw new IllegalStateException("network interceptor " + interceptors.get(index - 1)
                    + " must call proceed() exactly once");
        }

        // Call the next interceptor in the chain.
        RealInterceptorChain next = new RealInterceptorChain(
                interceptors, streamAllocation, httpCodec, connection, index + 1, request);
        Interceptor interceptor = interceptors.get(index);
        Response response = interceptor.intercept(next);

        // Confirm that the next interceptor made its required call to chain.proceed().
        if (httpCodec != null && index + 1 < interceptors.size() && next.calls != 1) {
            throw new IllegalStateException("network interceptor " + interceptor
                    + " must call proceed() exactly once");
        }

        // Confirm that the intercepted response isn't null.
        if (response == null) {
            throw new NullPointerException("interceptor " + interceptor + " returned null");
        }
        return response;
    }
复制代码

The most refined three core code from the above code:

// Call the next interceptor in the chain.
//每次调用取出下一个拦截器,index = index+1就表示下一个拦截器的索引
        RealInterceptorChain next = new RealInterceptorChain(
                interceptors, streamAllocation, httpCodec, connection, index + 1, request);
//取出要处理的拦截器
        Interceptor interceptor = interceptors.get(index);
 //调用每个拦截器的intercept方法,每个拦截器中都要调用chain的proceed方法,这样就是相当于把请求传递到下一个拦截器处理
        Response response = interceptor.intercept(next);
复制代码

This code implements three different request interceptor processing and transfer downward. The above code has several key parameters: interceptors: interceptors set, all the interceptors are stored in this collection; index: interceptor index, an index for indicating the current position of the interceptor in the process list interceptors ; when the implement custom interceptors, must not forget proceed method invocation chain, otherwise the chain will break.

"Chain" of creation

Run okhttp understand the interceptor chain, take a look at how this chain is created, and by default creates a framework which interceptors. Back RealCall objects, initiated by the request, to achieve the following reference code getResponseWithInterceptorChain:

Response getResponseWithInterceptorChain() throws IOException {
    // Build a full stack of interceptors.
    List<Interceptor> interceptors = new ArrayList<>();
    //添加用户创建的拦截器到拦截器链中,并先于系统默认的拦截器之前执行
    interceptors.addAll(client.interceptors());
    //用于错误恢复和重定向跟踪,创建了后面要使用的StreamAllocation类
    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);
    //通过拦截器执行具体的请求
    return chain.proceed(originalRequest);
  }
复制代码

This method creates the default of several core interceptors, and interceptors added to the collection, then create a Chain, and calls proceed method, which began processing the request.

to sum up


Previous analysis of the creation and operation mode of the interceptor chain okhttp in the core part of the framework are in this. It supports the operation and extend this framework, we can savor! Grasp the idea of ​​running this framework, we will be following several in-depth analysis of the core framework of default interceptor.

Guess you like

Origin juejin.im/post/5d463ef9e51d45621320309e