源码分析:Android Okhttp源码浅析(一)

Okhttp的调用


分析源码,我们都需要通过调用来查看源码的每一步都做了什么事情。

看下异步调用

 OkHttpClient client = new OkHttpClient();
        Request request = new Request.Builder().url("").build();
        client.newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
            }

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

源码分析。


我们首先看下,OkHttpClient初始化做的事情

public OkHttpClient() {
    this(new Builder());
  }

  OkHttpClient(Builder builder) {
    //调度器
    this.dispatcher = builder.dispatcher;
    this.proxy = builder.proxy;
    this.protocols = builder.protocols;
    this.connectionSpecs = builder.connectionSpecs;
    this.interceptors = Util.immutableList(builder.interceptors);
    this.networkInterceptors = Util.immutableList(builder.networkInterceptors);
    this.proxySelector = builder.proxySelector;
    ...
    this.readTimeout = builder.readTimeout;
    this.writeTimeout = builder.writeTimeout;
    this.pingInterval = builder.pingInterval;
  }
  ...
    public Builder() {
      dispatcher = new Dispatcher();
        ...
      connectTimeout = 10_000;
      readTimeout = 10_000;
      writeTimeout = 10_000;
      pingInterval = 0;
    }


这里我们看到,Okhttp是通过建造者模式初始化的。做的事情,主要是一些常用的配置。
(初始化调度器,缓存策略,连接时间等等)

我们接着看Request的初始化

public final class Request {
  final HttpUrl url;
  final String method;
  final Headers headers;
  final RequestBody body;
  final Object tag;

  Request(Builder builder) {
    this.url = builder.url;
    this.method = builder.method;
    this.headers = builder.headers.build();
    this.body = builder.body;
    this.tag = builder.tag != null ? builder.tag : this;
  }
    ...
}


我们可以看到,Request里面,主要是通过建造者模式,配置进行网络请求的url,method,header等等内容。

接着看client.newCall(request)


上面做的事情都是配置网络请求的信息。下面,这个调用会执行什么呢。

  @Override public Call newCall(Request request) {
    return new RealCall(this, request, false /* for web socket */);
  }

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


我们发现这句代码非常简单,就做了一件事。把上面我们构建好的Okhttp,Request传给RealCall。
并初始化它。

最后看下执行call.enqueue(Callback)


我们看下最后是怎么执行的呢

  @Override public void enqueue(Callback responseCallback) {
    //检查是否已经执行了。
    synchronized (this) {
      if (executed) throw new IllegalStateException("Already Executed");
      executed = true;
    }
    captureCallStackTrace();
    //把我们需要监听的返回callback传给AsyncCall,并初始化
    //调用我们okhttp创建的dispatcher的enqueue()方法。
    client.dispatcher().enqueue(new AsyncCall(responseCallback));
  }


我们看下AysncCall这个类

 final class AsyncCall extends NamedRunnable {
    private final Callback responseCallback;

    AsyncCall(Callback responseCallback) {
      super("OkHttp %s", redactedUrl());
      this.responseCallback = responseCallback;
    }


它的父类

public abstract class NamedRunnable implements Runnable {
  @Override public final void run() {
        ...
      execute();
        ...
  }

  protected abstract void execute();
}


我们发现AsyncCall是一个线程,并且父类实现了run()方法,并重新抽象了一个execute()方法,在run()里面调用。让AsyncCall来实现这个execute()方法。
如果调用这个线程的话,AsyncCall的execute()方法就会执行。

再看看 client.dispatcher().enqueue(AsyncCall)


看下这个里面做了什么操作。

public final class Dispatcher {
      private int maxRequests = 64;
  private int maxRequestsPerHost = 5;
  /** Ready async calls in the order they'll be run. */
    //这个是准备执行,异步任务的队列
  private final Deque<AsyncCall> readyAsyncCalls = new ArrayDeque<>();

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

  /** Running synchronous calls. Includes canceled calls that haven't finished yet. */
    //这个是正在执行的同步任务的队列
  private final Deque<RealCall> runningSyncCalls = new ArrayDeque<>();

    获取线程池
  public synchronized ExecutorService executorService() {
    if (executorService == null) {
        //核心线程数为9,最大线程数Integer.MAX_VALUE,保留时间60秒
      executorService = new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60, TimeUnit.SECONDS,
          new SynchronousQueue<Runnable>(), Util.threadFactory("OkHttp Dispatcher", false));
    }
    return executorService;
  }
    ...

  synchronized void enqueue(AsyncCall call) {
    //判断正在执行异步任务的队列数量是不是已经达到最大值了
    //如果没有到最大值,并且host数量小于5。
    //我们就把这个线程放到正在执行的队列里,并执行它
    if (runningAsyncCalls.size() < maxRequests && runningCallsForHost(call) < maxRequestsPerHost) {
        //添加
      runningAsyncCalls.add(call);
        //执行
      executorService().execute(call);
    } else {
        //否则,我们就放到准备执行的异步任务队列里
      readyAsyncCalls.add(call);
    }
  }
}


到这里,我们发现它确实就是一个调度器。
我们假设可以执行。我们看下AsyncCall的execute()方法,都做了什么

AsyncCall的execute()方法

@Override protected void execute() {
      boolean signalledCallback = false;
      try {
        注:1
        Response response = getResponseWithInterceptorChain();
        //如果没有取消的话,就调用callback的onResponse,否则就调用onFailure。
        if (retryAndFollowUpInterceptor.isCanceled()) {
          signalledCallback = true;
          responseCallback.onFailure(RealCall.this, new IOException("Canceled"));
        } else {
          signalledCallback = true;
          responseCallback.onResponse(RealCall.this, response);
        }
      } catch (IOException e) {
        if (signalledCallback) {
          // Do not signal the callback twice!
          Platform.get().log(INFO, "Callback failure for " + toLoggableString(), e);
        } else {
          responseCallback.onFailure(RealCall.this, e);
        }
      } finally {
        //注:2
        client.dispatcher().finished(this);
      }
    }
  }


这里,我们先不管注:1注:2。这就不管成功还是失败,就把数据返回给了我们的callback。

接着,先看下注:2。它是在finally里面执行的。所以执行完后,不管有没有异常,这个方法总会执行的,我们先看下这个。

client.dispatcher().finished(this)

 /** Used by {@code AsyncCall#run} to signal completion. */
  void finished(AsyncCall call) {
    //调用重载方法,第三个参数为true
    finished(runningAsyncCalls, call, true);
  }

  private <T> void finished(Deque<T> calls, T call, boolean promoteCalls) {
    int runningCallsCount;
    Runnable idleCallback;
    //同步
    synchronized (this) {
        //这里把我们执行完的call移除了
      if (!calls.remove(call)) throw new AssertionError("Call wasn't in-flight!");
        //调用了promoteCalls()方法
      if (promoteCalls) promoteCalls();
      runningCallsCount = runningCallsCount();
      idleCallback = this.idleCallback;
    }

    if (runningCallsCount == 0 && idleCallback != null) {
      idleCallback.run();
    }
  }


···
private void promoteCalls() {
    //再来判断是否,正在运行的队列大于,最大的请求队列。如果还大于就返回
    if (runningAsyncCalls.size() >= maxRequests) return; // Already running max capacity.
    //如果等待的队列是空的,也返回
    if (readyAsyncCalls.isEmpty()) return; // No ready calls to promote.
    //遍历等待的队列
    for (Iterator<AsyncCall> i = readyAsyncCalls.iterator(); i.hasNext(); ) {
      AsyncCall call = i.next();
        //如果执行的队列Host不大于最大的host。
        //把这个准备的任务,从等待队列移除,放到正在执行的队列,并立即执行。
      if (runningCallsForHost(call) < maxRequestsPerHost) {
        i.remove();
        runningAsyncCalls.add(call);
        executorService().execute(call);
      }
        //直到达到了最大的请求数量,就返回
      if (runningAsyncCalls.size() >= maxRequests) return; // Reached max capacity.
    }
  }


这里,我们就看完了一个任务完成后,做的事情。
1,移除完成的任务
2,判断正在运行的队列,是否还大于最大的请求数。
3,如果大于就返回,如果不大于就从等待的队列里面去取任务并执行,直到达到了,最大的请求数。

现在,我们就差分析,是怎么返回的Response的了。接下来,我们就看下它是怎么执行的。

Response response = 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));
    //初始化一个RealInterceptorChain跟Request,把拦截器都传进去
    Interceptor.Chain chain = new RealInterceptorChain(
        interceptors, null, null, null, 0, originalRequest);
    //调用proceed()方法
    return chain.proceed(originalRequest);
  }


这里也非常简单,把我们自己设置的拦截器和它自身的,都放到集合里。跟Request一块传给RealInterceptorChain。并调用proceed()方法。

我们再进去看看proceed犯法

RealInterceptorChain.proceed(originalRequest);

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

    calls++;
    ...

    // Call the next interceptor in the chain.
    //初始化,角标+1,取出interceptor调用intercept方法
    RealInterceptorChain next = new RealInterceptorChain(
        interceptors, streamAllocation, httpCodec, connection, index + 1, request);
    Interceptor interceptor = interceptors.get(index);
    //并把下一个RealInterceptorChain穿进去,index+1
    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;
  }


这里就是创建下一个拦截器。
调用当前拦截器的intercept(next)方法,把下一个拦截器传进去。

  • 我们自己的interceptor
  • retryAndFollowUpInterceptor
  • BridgeInterceptor
  • CacheInterceptor
  • ConnectInterceptor
  • NetworkInterceptors
  • 我们自己的networkInterceptors
  • CallServerInterceptor

我们看下拦截器是怎么传下去的

RetryAndFollowUpInterceptor.java
@Override public Response intercept(Chain chain) throws IOException {
    ...
     response = ((RealInterceptorChain) chain).proceed(request, streamAllocation, null, null);
    ...
}
BridgeInterceptor.java
  @Override public Response intercept(Chain chain) throws IOException {
        Response networkResponse = chain.proceed(requestBuilder.build());
    }
...


都是调用下一个构造的chain的proceed方法。
然后,在里面构造下一个chain,执行intercept方法。

* 拦截器的作用:*

  • 对当前的request请求做处理(添加/删除头信息等)。
  • 调用下一个拦截器。
  • 对响应的Response结果,做处理(写入缓存等),并返回给上一个拦截器。

调用完之后,响应Response。整个流程完成。

下一次,看下拦截器都做了什么功能呢。

猜你喜欢

转载自blog.csdn.net/ecliujianbo/article/details/79807919