okHttp源码分析-1 执行流程

okHttp源码分析-二 RetryAndFollowUpIntercept 重定向拦截器
okHttp源码分析-三 BridgeInterceptor 桥接拦截器
okHttp源码解析-四 缓存拦截器 CacheInterceptor
okhttp源码解析-五 链接拦截器 ConnectInterceptor

1.简单使用

创建okhttpClient对象
创建request对象
然后调用newCall
再调用enqueue()异步方法,里面传入一个监听回调方法。

  OkHttpClient okHttpClient = new OkHttpClient();
        Request request = new Request.Builder().url("http://baidu.com").build();
        okHttpClient.newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure( Call call, IOException e) {
            }
            @Override
            public void onResponse( Call call,  Response response) throws IOException {

            }
        });

2.源码分析

2.1 okhttpclient构造

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

里面创建Builder对象

 public Builder() {
      dispatcher = new Dispatcher(); // 分发器对象,很重要
      protocols = DEFAULT_PROTOCOLS;
      connectionSpecs = DEFAULT_CONNECTION_SPECS;
     ...
    }

进入dispatcher对象

public final class Dispatcher {
  private int maxRequests = 64;
  private int maxRequestsPerHost = 5;
  private Runnable idleCallback;

  /** Executes calls. Created lazily. */
  private ExecutorService executorService;

  /** 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 Dispatcher(ExecutorService executorService) {
    this.executorService = executorService;
  }

  public Dispatcher() {
  }

  public synchronized ExecutorService executorService() {
    if (executorService == null) {
      executorService = new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60, TimeUnit.SECONDS,
          new SynchronousQueue<Runnable>(), Util.threadFactory("OkHttp Dispatcher", false));
    }
    return executorService;
  }

readyAsyncCalls 等待的异步队列
runningAsyncCalls 正在运行的异步队列
runningSyncCalls 正在运行的同步队列
同时还有线程池对象executorService

    public ThreadPoolExecutor(int corePoolSize, //核心线程数量
                              int maximumPoolSize,//最大线程数量
                              long keepAliveTime,//存活的时间
                              TimeUnit unit,// 时间单位
                              BlockingQueue<Runnable> workQueue, // 锁队列
                              ThreadFactory threadFactory) { // 线程对象
        this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
             threadFactory, defaultHandler);
    }

上面创建核心对象涉及的类先记录,下面会用到。

2.2 new Request.Builder()

该对象使用建造者模式来构建,进入方法,默认请求方法get,创建了header对象

  public Builder() {
      this.method = "GET";
      this.headers = new Headers.Builder();
    }

new Request.Builder()使用了建造者模式,所以最终还是调用build();

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

  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;
  }

这些很简单,不叙述,大致就是准备请求头,url、body

2.3 newCall()

 /**
   * Prepares the {@code request} to be executed at some point in the future.
   */
  @Override public Call newCall(Request request) {
  	// 创建RealCall对象
    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);
  }

realcall对象就是真正请求对象的封装。创建RealCall的时候,创建了RetryAndFollowUpInterceptor类,就是重定向拦截器。后面说。

2.4 enqueue 异步方法

再往下看enqueue ,它是一个接口的方法,其实现就是realCall对象。

  @Override 
  public void enqueue(Callback responseCallback) {
  // 同步代码块
    synchronized (this) {
    	如果已经执行,抛出异常
      if (executed) throw new IllegalStateException("Already Executed");
      executed = true;
    }
    captureCallStackTrace();
	//    分发器执行异步操作
    client.dispatcher().enqueue(new AsyncCall(responseCallback));
  }

 
  synchronized void enqueue(AsyncCall call) {
    if (runningAsyncCalls.size() < maxRequests && runningCallsForHost(call) < maxRequestsPerHost) {
      runningAsyncCalls.add(call);
      executorService().execute(call);
    } else {
      readyAsyncCalls.add(call);
    }
  }

enqueue 方法开始异步处理队列的方法,正在运行的队列大小小于最大请求数量(64)且正在运行的host 小于最大请求host数量(5),把当前任务AsyncCall加入运行队列且执行任务,否则的话加入到准备队列中。

2.5 AsyncCall

该对象继承NamedRunnable,而NamedRunnable又是一个线程对象,所以就看run方法了

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 {
  	// 看重点,抽象方法,看子类喽,谁是它的子类,就是AsyncCall啊
    execute();
  } finally {
    Thread.currentThread().setName(oldName);
  }
}

protected abstract void execute();
}


 @Override protected void execute() {
   boolean signalledCallback = false;
   try {
   // 获取一个响应对象,重点
     Response response = getResponseWithInterceptorChain();
     if (retryAndFollowUpInterceptor.isCanceled()) {
       signalledCallback = true;
       responseCallback.onFailure(RealCall.this, new IOException("Canceled"));
     } else {
       signalledCallback = true;
//responseCallback 就是使用new CallBack对象,去响应成功和失败
       responseCallback.onResponse(RealCall.this, response);
     }
   } catch (IOException e) {
     ...
   } finally {
//      这也要看下
     client.dispatcher().finished(this);
   }
 }

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

getResponseWithInterceptorChain 方法是okhttp的核心,里面是责任链模式。五个拦截器组成链式结构,去处理网络请求。
retryAndFollowUpInterceptor:当请求失败,会自动重连,或者重定向
BridgeInterceptor 主要处理请求头信息
CacheInterceptor 处理缓存信息
ConnectInterceptor 查找可用的连接
CallServerInterceptor 真正去请求服务器的拦截器

2.6 chain.proceed方法

责任链的执行方法proceed

  public Response proceed(Request request, StreamAllocation streamAllocation, HttpCodec httpCodec,
      Connection 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 && !sameConnection(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.
    // 重点:创建一个新的拦截器的链式对象,然后传入index+1,意思就是取下一个
    //拦截器对象,第一个对象就是重定向拦截器,然后调用intercept方法。
//因为Interceptor是个接口,所以就会调用接口的实现类去执行,
//就是重定向拦截器的interceptor方法。
    RealInterceptorChain next = new RealInterceptorChain(
        interceptors, streamAllocation, httpCodec, connection, index + 1, request);
     //
    Interceptor interceptor = interceptors.get(index);
    Response response = interceptor.intercept(next);

   ...
    return response;
  }

先获取第一个拦截器interceptors.get(index);然后调用intercept方法,传入下一个拦截器,嵌套调用。

RealInterceptorChain next = new RealInterceptorChain(
interceptors, streamAllocation, httpCodec, connection, index + 1

如当重定向拦截器处理完任务后,还会再次调用realChain.proceed()方法,继续调用其他拦截器。至此,大体流程完毕。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值