okhttp网络框架源码解析

一、同步/异步请求代码简单实现

OkHttpClient client = new OkHttpClient.Builder().readTimeout(5, TimeUnit.SECONDS).build();
//同步请求
public void synRequest(){
    Request request = new Request.Builder().url("http://www.baidu.com").get().build();
    Call call = client.newCall(request);
    try {
       Response response =  call.execute();
        Log.e(TAG, "synRequest: "+response.body().string() );
    } catch (IOException e) {
        e.printStackTrace();
    }
}

//异步请求(onFailure和onResponse均在工作线程回调)
public void asyRequest(){
    Request request = new Request.Builder().url("http://www.baidu.com").get().build();
    Call call = client.newCall(request);
    call.enqueue(new Callback() {
        @Override
        public void onFailure(Call call, IOException e) {

        }

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

二、OKhttp请求源码分析
1、创建OKhttpClient对象
OKhttpClient的Builder方法源码分析:
Builder为OKhttpClient中的静态内部类

public Builder() {
  dispatcher = new Dispatcher();
  protocols = DEFAULT_PROTOCOLS;
  connectionSpecs = DEFAULT_CONNECTION_SPECS;
  eventListenerFactory = EventListener.factory(EventListener.NONE);
  proxySelector = ProxySelector.getDefault();
  cookieJar = CookieJar.NO_COOKIES;
  socketFactory = SocketFactory.getDefault();
  hostnameVerifier = OkHostnameVerifier.INSTANCE;
  certificatePinner = CertificatePinner.DEFAULT;
  proxyAuthenticator = Authenticator.NONE;
  authenticator = Authenticator.NONE;
  connectionPool = new ConnectionPool();
  dns = Dns.SYSTEM;
  followSslRedirects = true;
  followRedirects = true;
  retryOnConnectionFailure = true;
  connectTimeout = 10_000;
  readTimeout = 10_000;
  writeTimeout = 10_000;
  pingInterval = 0;
}


dispatcher是OKhttp中比较核心的一个类,是分发器类,可以决定异步请求是缓存还是执行,把同步请求放入请求队列。

2、构建携带请求信息的Request对象
Request的builder方法源码分析:

public Builder() {
  this.method = "GET";//定义请求方式为get
  this.headers = new Headers.Builder(); //创建Header用于保存请求头部信息
}


build()方法源码,就是把之前配置好的请求方法、头部信息、URL传给Request对象:

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

Request的构造方法源码,里面就是请求的一些信息:

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

3、call的newCall实际调用的RealCall
RealCall的构造方法:

private RealCall(OkHttpClient client, Request originalRequest, boolean forWebSocket) {
    this.client = client; //之前创建的client对象
    this.originalRequest = originalRequest; //之前的request请求
    this.forWebSocket = forWebSocket;
    this.retryAndFollowUpInterceptor = new RetryAndFollowUpInterceptor(client, forWebSocket); //维护了重定向拦截器
}

RealCall 的execute方法实现:

@Override public Response execute() throws IOException {
    synchronized (this) {
      //同一个http请求只能执行一次,如果没有就把executed设为true,如果执行过则抛出异常
      if (executed) throw new IllegalStateException("Already Executed");
      executed = true;
    }
    //捕捉http请求的异常堆栈信息
    captureCallStackTrace();
    //监听方法,每当http请求开启execute或enqueue都会开启此监听方法
    eventListener.callStart(this);
    try {
     //
      client.dispatcher().executed(this);
      Response result = getResponseWithInterceptorChain(); //拦截器链方法
      if (result == null) throw new IOException("Canceled");
      return result;
    } catch (IOException e) {
      eventListener.callFailed(this, e);
      throw e;
    } finally {
      client.dispatcher().finished(this);//主动回收同步请求
    }
}

client.dispatcher().executed(),dispatcher的同步请求将请求添加到队列之中

synchronized void executed(RealCall call) {
    runningSyncCalls.add(call);
}

runningSyncCalls队列在dispatch中定义:

/** 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<>(); //同步执行队列

同步请求中dispatch的finish方法源码:

void finished(RealCall call) {
    finished(runningSyncCalls, call, false);
}

private <T> void finished(Deque<T> calls, T call, boolean promoteCalls) {
    int runningCallsCount;
    Runnable idleCallback;
    synchronized (this) {
      //在同步请求队列中移除异步方法,如果不能移除则抛出异常
      if (!calls.remove(call)) throw new AssertionError("Call wasn't in-flight!");
      //同步请求此方法以下方法不会被调用
      if (promoteCalls) promoteCalls();
      //runningCallsCount计算执行的异步和同步请求
      runningCallsCount = runningCallsCount();
      idleCallback = this.idleCallback;
    }

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

runningCallsCount源码:

public synchronized int runningCallsCount() {
   //正在执行的异步请求和同步请求之和
   return runningAsyncCalls.size() + runningSyncCalls.size();
}

RealCall的enqueue方法源码分析
@Override public void enqueue(Callback responseCallback) {
synchronized (this) {
  if (executed) throw new IllegalStateException("Already Executed");
  executed = true;
}
captureCallStackTrace();
eventListener.callStart(this);
client.dispatcher().enqueue(new AsyncCall(responseCallback));
}

AsyncCall源码:
//AsyncCall 继承NamedRunnable

final class AsyncCall extends NamedRunnable {
    private final Callback responseCallback;
    ......
}

NamedRunnable源码:

//NamedRunnable实际实现了Runnable接口
public abstract class NamedRunnable implements Runnable {
    protected final String name;
    ......
}

继续分析dispatch的enqueue方法:

private int maxRequests = 64;
private int maxRequestsPerHost = 5;
......
synchronized void enqueue(AsyncCall call) {
    //判断正在运行的异步请求数是否小于最大请求数,每台主机的运行请求数是否小于每台主机的最大请求数
    if (runningAsyncCalls.size() < maxRequests && runningCallsForHost(call) < maxRequestsPerHost) {
      runningAsyncCalls.add(call);
      executorService().execute(call);
    } else {
      readyAsyncCalls.add(call);
    }
}

异步请求会先判断运行的异步请求数是否小于64,每台主机的运行请求数是否小于5,才会把请求添加到请求队列中,然后由线程池去执行请求。如果不是就会把该请求加到等待队列中。

线程池对象executorService的源码分析:

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

executorService的execute方法的实现在AsyncCall的execute方法中,源码如下:

 

@Override protected void execute() {
  boolean signalledCallback = false;
  try {
    Response response = getResponseWithInterceptorChain();
    //当重试拦截器被取消,会调用onFailure方法,否则会调用onResponse方法
    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 {
      eventListener.callFailed(RealCall.this, e);
      responseCallback.onFailure(RealCall.this, e);
    }
  } finally {
    client.dispatcher().finished(this);
  }
}

异步的dispatch的finished方法:

void finished(AsyncCall call) {
finished(runningAsyncCalls, call, true);
}
......
private <T> void finished(Deque<T> calls, T call, boolean promoteCalls) {
    int runningCallsCount;
    Runnable idleCallback;
    synchronized (this) {
      if (!calls.remove(call)) throw new AssertionError("Call wasn't in-flight!");
      if (promoteCalls) promoteCalls();
      runningCallsCount = runningCallsCount();
      idleCallback = this.idleCallback;
    }

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

总结:

1.创建一个OkHttpClient对象

2.构建一个Request对象,通过OkHttpClient和Request对象,构建出Call对象

3.执行call的enqueue方法

-------------------------------------------------------------------------------------------------------------------------------------------------------------------------

OkHttp拦截器
官网:拦截器是OkHttp中提供一种强大机制,它可以实现网络监听、请求以及相应重写、请求失败重试等功能

RetryAndFollowUpInterceptor

BridgeInterceptor

CacheInterceptor

ConnectInterceptor

CallServerInterceptor

1.创建一系列拦截器,并将其放入一个连接器list中
2.创建一个拦截器链RealInterceptorChain,并执行拦截器链的proceed方法

1.在发起请求前对request进行处理
2.调用下一个拦截器,获取respose
3.对response进行处理,返回上一个拦截器


RetryAndFollowUpInterceptor
1.创建StreamAllocation对象
2.调用RealInterceptorChain.proceed(...)进行网络请求
3.根据异常结果或者响应结果判断是否进行重新请求
4.调用下一个拦截器,对respose进行处理,返回给上一个拦截器


BridgeInterceptor
1.负责将用户构建的一个Request请求转化为能够进行网络访问的请求
2.将这个符合网络请求的Request进行网络请求
3.将网络请求回来的响应Response转化为用户可用的Response


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值