責任鏈模式的應用:Retrofit2 + OkHttp3 配置及Interceptor原理

Okhttp的Interceptor攔截器源碼解析

OkHttp的調用流程:
在調用client.newCall(request)將會調用到RealCall.newRealCall(this, request, false);方法,之後將會調用到RealCall.getResponseWithInterceptorChain()函數,而在其中將進行攔截器鏈的構建。

RealCall.java
核心代碼:
Response result = getResponseWithInterceptorChain();
通過getResponseWithInterceptorChain完成對攔截器的構建

  @Override public Response execute() throws IOException {
    synchronized (this) {
      if (executed) throw new IllegalStateException("Already Executed");
      executed = true;
    }
    captureCallStackTrace();
    try {
      client.dispatcher().executed(this);
      Response result = getResponseWithInterceptorChain();
      if (result == null) throw new IOException("Canceled");
      return result;
    } finally {
      client.dispatcher().finished(this);
    }
  }

getResponseWithInterceptorChain()
包含自定義攔截器
重定向與失敗重試retryAndFollowUpInterceptor
用戶的請求頭處理,響應處理Cookie持久性策略 BridgeInterceptor

緩存請求、響應緩存的寫入 (客戶端設置的緩存策略)CacheInterceptor
發送請求,讀取服務器的響應CallServerInterceptor
最後通過RealInterceptorChain調用proceed接口啓動攔截器。

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);
    return chain.proceed(originalRequest);
  }

幾個管件類和接口

Interceptor.java

public interface Interceptor {
  Response intercept(Chain chain) throws IOException;

  interface Chain {
    Request request();

    Response proceed(Request request) throws IOException;

    Connection connection();
  }
}

RealInterceptorChain.java

public final class RealInterceptorChain implements Interceptor.Chain {
  private final List<Interceptor> interceptors;
  private final StreamAllocation streamAllocation;
  private final HttpCodec httpCodec;
  private final Connection connection;
  private final int index;
  private final Request request;
  private int calls;

  public RealInterceptorChain(List<Interceptor> interceptors, StreamAllocation streamAllocation,
      HttpCodec httpCodec, Connection connection, int index, Request request) {
    this.interceptors = interceptors;
    this.connection = connection;
    this.streamAllocation = streamAllocation;
    this.httpCodec = httpCodec;
    this.index = index;
    this.request = request;
  }

  ...

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

  public Response proceed(Request request, StreamAllocation streamAllocation, HttpCodec httpCodec,
      Connection connection) throws IOException {
    ...

    // 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);

    ...

    return response;
  }

  
}

RealInterceptorChain實現了Interceptor接口,調用源頭來自於RealCall的getResponseWithInterceptorChain方法

調用流程:
1.加入自定義攔截器。然後將okhttp內置的一些攔截器按照功能順序add進list裏。
2.定義整個攔截器工作的源頭。new一個RealInterceptorChain,idnex爲0,把初始的request傳了進去,然後調用proceed獲取請求的response
3.RealInterceptorChain實現了Interceptor.Chain接口,在proceed方法中獲取上一個攔截器包裝的Request,然後將下一個攔截器和整個Request的信息包裝成RealInterceptorChain,並且會調用當前攔截器的intercept方法把下一個攔截器(RealInterceptorChain)傳進去,並且獲取到Response
4.CallServerInterceptor的Interceptor完成最終的網絡請求並返回response

在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章