OkHttp源码(一)

同步请求示例

 //实例化请求客户端
        OkHttpClient okHttpClient = new OkHttpClient.Builder()
                .readTimeout( 5, TimeUnit.SECONDS )
                .build();
        //实例化请求对象
        Request request = new Request.Builder()
                .url( "http://www.baidu.com" )
                .get()
                .build();
        //和服务端建立连接的call
        Call call = okHttpClient.newCall( request );
        try {
            //同步请求,返回体,同步会阻塞线程直到响应
            Response response = call.execute();
            String s = response.body().toString();
            Log.i( TAG, "synRequest:>>>"+s );
        } catch (IOException e) {
            e.printStackTrace();
        }

异步请求示例

 //实例化请求客户端
        OkHttpClient okHttpClient = new OkHttpClient.Builder()
                .readTimeout( 5, TimeUnit.SECONDS )
                .cache( new Cache( new File( "cache" ),20*1024*1024 ) )//缓存大小
                .build();
        //实例化请求对象
        Request request = new Request.Builder()
                .url( "http://www.baidu.com" )
                .get()
                .build();
        //和服务端建立连接的call
        Call call = okHttpClient.newCall( request );

        //异步请求
        call.enqueue( new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                Log.i( TAG, "onFailure:>>>" );
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                Log.i( TAG, "onResponse:>>>"+response.body().string() );
            }
        } );

同步和异步调用只有在最后发起请求时有差别,前面构造OkHttpClient ,Request ,Call 流程相同。我们先看OkHttpClient.Builder()的构造过程。

public static final class Builder {
    Dispatcher dispatcher;//是同步还是异步的分发
   ......
    ConnectionPool connectionPool;//连接池
   ......
    int readTimeout;//读取超时
   ,,,,,,

    
    public Builder() {
      dispatcher = new Dispatcher();
      ......
      connectionPool = new ConnectionPool();
      ......
}

//保存到成员变量
public Builder readTimeout(long timeout, TimeUnit unit) {
      readTimeout = checkDuration("timeout", timeout, unit);
      return this;
    }

// 构造OkHttpClient
 public OkHttpClient build() {
      return new OkHttpClient(this);
    }

Builder 模式将我们设置的参数全部保留到成员变量,再build时构造OkHttpClient,并把自己(Builder )传给OkHttpClient。因为一个客户端可以同时发起同步和异步请求,也可以同时发送多个请求,因此Dispatcher和ConnectionPool在客户端就要构造出来。

  public static class Builder {
    @Nullable HttpUrl url;
    String method;
    Headers.Builder headers;
    @Nullable RequestBody body;

   
    Map, Object> tags = Collections.emptyMap();

    public Builder() {
      this.method = "GET";//默认get请求
      this.headers = new Headers.Builder();
    }

    Builder(Request request) {
      this.url = request.url;
      this.method = request.method;
      this.body = request.body;
      this.tags = request.tags.isEmpty()
          ? Collections., Object>emptyMap()
          : new LinkedHashMap<>(request.tags);
      this.headers = request.headers.newBuilder();
    }

    public Request build() {
      if (url == null) throw new IllegalStateException("url == null");
      return new Request(this);
    }

Request包含了请求的报文信息,即请求地址、请求方式、请求头、请求体,它的构建方式和OkHttpClient一样。Call 的构造方式和前面两者不同,它通过RealCall的newRealCall静态方法来构造。

public class OkHttpClient implements Cloneable, Call.Factory, WebSocket.Factory {
  .....
 @Override public Call newCall(Request request) {
    return RealCall.newRealCall(this, request, false /* for web socket */);
  }
final class RealCall implements Call {
  final OkHttpClient client;
  //构造重定向拦截器
  final RetryAndFollowUpInterceptor retryAndFollowUpInterceptor;
  final AsyncTimeout timeout;
  private @Nullable EventListener eventListener;
  final Request originalRequest;
  final boolean forWebSocket;
  private boolean executed;
  private RealCall(OkHttpClient client, Request originalRequest, boolean forWebSocket) {
    this.client = client;
    this.originalRequest = originalRequest;
    this.forWebSocket = forWebSocket;
    //构造重定向拦截器
    this.retryAndFollowUpInterceptor = new RetryAndFollowUpInterceptor(client, forWebSocket);
    this.timeout = new AsyncTimeout() {
      @Override protected void timedOut() {
        cancel();
      }
    };
    this.timeout.timeout(client.callTimeoutMillis(), MILLISECONDS);
  }

  static RealCall newRealCall(OkHttpClient client, Request originalRequest, boolean forWebSocket) {
    // 在静态方法里创建
    RealCall call = new RealCall(client, originalRequest, forWebSocket);
    call.eventListener = client.eventListenerFactory().create(call);
    return call;
  }

源码跟踪看到,Call 的实现只有一个RealCall子类 ,所有参数准备就绪,执行call.execute()同步请求,即调用RealCall 的execute方法

 @Override public Response execute() throws IOException {
    synchronized (this) {
      //同一个Call 请求只能执行一次,执行过将抛异常,这意味着如果要执行多个要重新调用newCall
      if (executed) throw new IllegalStateException("Already Executed");
      executed = true;
    }
    captureCallStackTrace();
    timeout.enter();
    eventListener.callStart(this);
    try {
    //从OkHttpClient获取创建好的Dispatcher,将RealCall加入到成员变量runningSyncCalls 同步队列中
      client.dispatcher().executed(this);
      //获取请求数据
      Response result = getResponseWithInterceptorChain();
      if (result == null) throw new IOException("Canceled");
      //将数据返回
      return result;
    } catch (IOException e) {
      e = timeoutExit(e);
      eventListener.callFailed(this, e);
      throw e;
    } finally {
      //移除掉队列里的某些请求
      client.dispatcher().finished(this);
    }
  }
public final class Dispatcher {
   private int maxRequests = 64;
   private int maxRequestsPerHost = 5;
   private @Nullable Runnable idleCallback;
    private @Nullable ExecutorService executorService;

 //异步就绪队列
  private final Deque readyAsyncCalls = new ArrayDeque<>();

  //异步的执行队列
  private final Deque runningAsyncCalls = new ArrayDeque<>();

  //同步队列
 private final Deque runningSyncCalls = new ArrayDeque<>();

  //加入到同步队列中
  synchronized void executed(RealCall call) {
    runningSyncCalls.add(call);
  }

  //请求流程完成,异步请求的回收重置
  void finished(AsyncCall call) {
    finished(runningAsyncCalls, call);
  }

 //请求流程完成,同步请求的回收重置
  void finished(RealCall call) {
    finished(runningSyncCalls, call);
  }


  private  void finished(Deque calls, T call) {
    Runnable idleCallback;
    synchronized (this) {
      
      if (!calls.remove(call)) throw new AssertionError("Call wasn't in-flight!");
      idleCallback = this.idleCallback;
    }

    boolean isRunning = promoteAndExecute();

    if (!isRunning && idleCallback != null) {
      //执行run方法
      idleCallback.run();
    }
  }

可以看到,同步请求的主要逻辑就是把RealCall加入到Dispatcher 维护的runningSyncCalls 队列中。
异步请求和同步请求前几步的创建没有差别,是在realCall执行请求时才区别开来,下面分析异步请求的调用流程。

final class RealCall implements Call {
  //执行请求并传入回调
  @Override public void enqueue(Callback responseCallback) {
    synchronized (this) {
    //每个call只能执行一次
      if (executed) throw new IllegalStateException("Already Executed");
      executed = true;
    }
    captureCallStackTrace();
    eventListener.callStart(this);
    //将传递进来的回调封装成AsyncCall
    client.dispatcher().enqueue(new AsyncCall(responseCallback));
  }

每个请求只能执行一次,executed用来判断是否已执行过,并且executed和连接池的实现原理相关,下面分析。最后一步看到,再获取分发器执行enqueue时,将我们出入的回调封装成了AsyncCall对象,它是RealCall的内部类,本质是一个Runnable。

final class RealCall implements Call {
    //继承了NamedRunnable 
    final class AsyncCall extends NamedRunnable {
        private final Callback responseCallback;

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

获取Dispatcher ,调用enqueue,将AsyncCall 传入

public final class Dispatcher {
  //异步请求
  void enqueue(AsyncCall call) {
    //加到就绪队列中
    synchronized (this) {
      readyAsyncCalls.add(call);
    }
    //从就绪队列取出
    promoteAndExecute();
  }

    //从就绪队列取出AsyncCall ,满足请求条件,则加入请求列表,再遍历列表交给线程池执行
 private boolean promoteAndExecute() {
    assert (!Thread.holdsLock(this));

    List executableCalls = new ArrayList<>();
    boolean isRunning;
    synchronized (this) {
      //遍历就绪队列
      for (Iterator i = readyAsyncCalls.iterator(); i.hasNext(); ) {
        AsyncCall asyncCall = i.next();
        //执行的请求最多64个
        if (runningAsyncCalls.size() >= maxRequests) break; // Max capacity.
        //host小于5
        if (runningCallsForHost(asyncCall) >= maxRequestsPerHost) continue; // Host max capacity.
        //取出
        i.remove();
      //添加到列表中
        executableCalls.add(asyncCall);
      //添加到执行队列中
        runningAsyncCalls.add(asyncCall);
      }
    //当前有执行的请求
      isRunning = runningCallsCount() > 0;
    }

    //从执行列表取出加入到线程池中执行
    for (int i = 0, size = executableCalls.size(); i < size; i++) {
      AsyncCall asyncCall = executableCalls.get(i);
      //获取线程池,调用executeOn
      asyncCall.executeOn(executorService());
    }

    return isRunning;
  }

  //创建线程池
  public synchronized ExecutorService executorService() {
    if (executorService == null) {
      //虽然最大线程数量用了Integer.MAX_VALUE,但上面分析知道实际不会超过64个
      //通过execute提交的AsyncCall会保存到SynchronousQueue这个队列中
      executorService = new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60, TimeUnit.SECONDS,
          new SynchronousQueue(), Util.threadFactory("OkHttp Dispatcher", false));
    }
    return executorService;
  }



  //当前请求数=同步执行数+异步执行数
  public synchronized int runningCallsCount() {
    return runningAsyncCalls.size() + runningSyncCalls.size();
  }
public final class Util {
//创建新线程的工厂
 public static ThreadFactory threadFactory(final String name, final boolean daemon) {
    return new ThreadFactory() {
      @Override public Thread newThread(Runnable runnable) {
        Thread result = new Thread(runnable, name);
        result.setDaemon(daemon);
        return result;
      }
    };
  }
}

Dispatcher 执行异步请求时,会先将Runnable(即AsyncCall )加入就绪队列中,然后遍历就绪队列,如果满足当前请求数小于等于64,host小于5个,则把当前Runnable移除就绪队列,加入到执行列表中,以等待执行,否则不加入,留在队列中。被添加到执行列表的Runnable将遍历取出,交由线程池执行。

//NamedRunnable 继承了Runnable 
public abstract class NamedRunnable implements Runnable {
  protected final String name;

  public NamedRunnable(String format, Object... args) {
    this.name = Util.format(format, args);
  }

  @Override public final void run() {
    String oldName = Thread.currentThread().getName();
    Thread.currentThread().setName(name);
    try {
      //执行子类的execute
      execute();
    } finally {
      Thread.currentThread().setName(oldName);
    }
  }

  protected abstract void execute();
}
final class RealCall implements Call {
  //重定向拦截器
  final RetryAndFollowUpInterceptor retryAndFollowUpInterceptor;

   private RealCall(OkHttpClient client, Request originalRequest, boolean forWebSocket) {
    this.client = client;
    this.originalRequest = originalRequest;
    this.forWebSocket = forWebSocket;
    //构造重定向拦截器
    this.retryAndFollowUpInterceptor = new RetryAndFollowUpInterceptor(client, forWebSocket);
    this.timeout = new AsyncTimeout() {
      @Override protected void timedOut() {
        cancel();
      }
    };
    this.timeout.timeout(client.callTimeoutMillis(), MILLISECONDS);
    }

    //继承了NamedRunnable 
    final class AsyncCall extends NamedRunnable {
        //保存回调
        private final Callback responseCallback;

        AsyncCall(Callback responseCallback) {
            super("OkHttp %s", redactedUrl());
            this.responseCallback = responseCallback;
        }
    String host() {
      return originalRequest.url().host();
    }

    Request request() {
      return originalRequest;
    }

    RealCall get() {
      return RealCall.this;
    }

    //线程池执行请求    
    void executeOn(ExecutorService executorService) {
      assert (!Thread.holdsLock(client.dispatcher()));
      boolean success = false;
      try {
        //执行run方法
        executorService.execute(this);
        success = true;
      } catch (RejectedExecutionException e) {
        InterruptedIOException ioException = new InterruptedIOException("executor rejected");
        ioException.initCause(e);
        eventListener.callFailed(RealCall.this, ioException);
        responseCallback.onFailure(RealCall.this, ioException);
      } finally {
        if (!success) {
          client.dispatcher().finished(this); // This call is no longer running!
        }
      }
    }

    //由run方法执行execute
    @Override 
    protected void execute() {
      boolean signalledCallback = false;
      timeout.enter();
      try {
        //获取返回数据,这里是拦截器链,下面分析
        Response response = getResponseWithInterceptorChain();
        //重定向拦截器是否取消了
        if (retryAndFollowUpInterceptor.isCanceled()) {
          signalledCallback = true;
          //失败回调onFailure
          responseCallback.onFailure(RealCall.this, new IOException("Canceled"));
        } else {
          //没有取消
          signalledCallback = true;
          //成功回调onResponse
          responseCallback.onResponse(RealCall.this, response);
        }
      } catch (IOException e) {
        e = timeoutExit(e);
        if (signalledCallback) {
          // Do not signal the callback twice!
          Platform.get().log(INFO, "Callback failure for " + toLoggableString(), e);
        } else {
          eventListener.callFailed(RealCall.this, e);
          responseCallback.onFailure(RealCall.this, e);
        }
      } finally {
        client.dispatcher().finished(this);
      }
    }

  }

由以上分析看到,遍历执行列表后,取出AsyncCall ,调用executeOn,将通过线程池的execute,来执行AsyncCall 的父类的run方法,run方法设置了线程名后,又调用了子类的execute方法,做实际的请求操作,如果重定向拦截器被取消了,则回调我们常见的onFailure方法,没有被取消,则成功回调onResponse方法。

上面分析了同步和异步请求的执行和数据回调的流程,但实际的请求流程还没有分析到。由源码看到,无论同步还是异步,都是通getResponseWithInterceptorChain()来获取请求数据的,其内部是通过实现一条拦截器链,来获取到网络数据的,下篇将分析拦截链调用和最终请求网络数据的流程。

你可能感兴趣的:(OkHttp源码(一))