文章目录
OkHttp 系列文章目录
一、分析 OkHttp 执行原理
1、创建 OkHttpClient
2、创建 Request
3、获取 RealCall
4、通过 RealCall 发送 同步 / 异步 Request 请求
( 1 ) 、同步 Request 请求
( 2 ) 、异步 Request 请求
二、OkHttp 异步 Request 请求源码分析
1、Dispatcher 调度器 enqueue 方法分析
2、Dispatcher 调度器 promoteAndExecute 方法分析
3、AsyncCall 的 executeOn 方法分析
三、OkHttp 请求时序图参考
四、博客资源
一、分析 OkHttp 执行原理
以 OkHttp 同步 / 异步 Get 请求为例 , 分析底层的运行细节 ;
/**
/** * OkHttp 异步 Get 请求 */ private void httpAsynchronousGet() { // 初始化 OkHttp OkHttpClient mOkHttpClient = new OkHttpClient(); // Request 中封装了请求相关信息 Request request = new Request.Builder() .url("https://www.baidu.com") // 设置请求地址 .get() // 使用 Get 方法 .build(); // 异步 Get 请求 mOkHttpClient.newCall(request).enqueue(new Callback(){ @Override public void onFailure(Call call, IOException e) { // 请求失败的情况 } @Override public void onResponse(Call call, Response response) throws IOException { // 请求成功 , 获取 String result = response.body().string(); Log.i(TAG, "result : " + result); runOnUiThread(new Runnable() { @Override public void run() { // 主线程中执行相关代码 } }); } }); }
1、创建 OkHttpClient
创建 OkHttpClient : 调用者调用 OkHttpClient 构造函数 , 创建 OkHttpClient , 然后返回给调用者 ;
OkHttpClient mOkHttpClient = new OkHttpClient();
OkHttpClient 构造函数中 , 实际上创建了自身的创建者 ; public OkHttpClient() { this(new Builder()); }
上述创建者构造函数调用的是无参构造函数 , 也就是默认设置了一系列参数 , 如下 :
public static final class Builder { public Builder() { dispatcher = new Dispatcher(); protocols = DEFAULT_PROTOCOLS; connectionSpecs = DEFAULT_CONNECTION_SPECS; eventListenerFactory = EventListener.factory(EventListener.NONE); proxySelector = ProxySelector.getDefault(); if (proxySelector == null) { proxySelector = new NullProxySelector(); } 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; callTimeout = 0; connectTimeout = 10_000; readTimeout = 10_000; writeTimeout = 10_000; pingInterval = 0; } }
2、创建 Request
创建 Request 时 , 使用 Request 的创建者 Request.Builder 创建该 Request 对象 ;
先调用 Request.Builder 的构造函数 , 创建 Request.Builder 对象 , 然后调用 Request.Builder 的 build 方法 , 创建 Request 对象 ;
// Request 中封装了请求相关信息 Request request = new Request.Builder() .url("https://www.baidu.com") // 设置请求地址 .get() // 使用 Get 方法 .build();
3、获取 RealCall
调用 OkHttpClient 对象的 newCall 方法 , 发起新的请求调用 , 返回 1 11 个 RealCall 类型对象 ;
mOkHttpClient.newCall(request)
在 OkHttpClient 的 newCall 方法中 , 创建了 RealCall , 并返回给了调用者 ;
/** * Prepares the {@code request} to be executed at some point in the future. */ @Override public Call newCall(Request request) { return RealCall.newRealCall(this, request, false /* for web socket */); }
RealCall 实现了 Call 接口 ;
final class RealCall implements Call { final OkHttpClient client; }
Call 接口提供的功能 : execute 是同步请求 , enqueue 是异步请求 ;
public interface Call extends Cloneable { Request request(); Response execute() throws IOException; void enqueue(Callback responseCallback); void cancel(); boolean isExecuted(); boolean isCanceled(); Timeout timeout(); Call clone(); interface Factory { Call newCall(Request request); } }
4、通过 RealCall 发送 同步 / 异步 Request 请求
RealCall 实现了上述 Call 接口的各项功能 , 主要关注其实现 Call 接口的 execute 同步请求方法 , enqueue 异步请求方法 ;
final class RealCall implements Call { @Override public Response execute() throws IOException { synchronized (this) { if (executed) throw new IllegalStateException("Already Executed"); executed = true; } transmitter.timeoutEnter(); transmitter.callStart(); try { client.dispatcher().executed(this); // 返回一个责任链 return getResponseWithInterceptorChain(); } finally { client.dispatcher().finished(this); } } @Override public void enqueue(Callback responseCallback) { synchronized (this) { if (executed) throw new IllegalStateException("Already Executed"); executed = true; } transmitter.callStart(); client.dispatcher().enqueue(new AsyncCall(responseCallback)); } }
( 1 ) 、同步 Request 请求
同步请求方法 , 返回一个责任链 , 在该方法中可以清楚的看到 OkHttp 的 Get 请求具体做了哪些步骤 ;
在该方法中通过添加不同功能的拦截器 , 实现相关业务路基 ;
Response getResponseWithInterceptorChain() throws IOException { // Build a full stack of interceptors. List<Interceptor> interceptors = new ArrayList<>(); interceptors.addAll(client.interceptors()); interceptors.add(new RetryAndFollowUpInterceptor(client)); // 处理网桥的链接器 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, transmitter, null, 0, originalRequest, this, client.connectTimeoutMillis(), client.readTimeoutMillis(), client.writeTimeoutMillis()); boolean calledNoMoreExchanges = false; try { Response response = chain.proceed(originalRequest); if (transmitter.isCanceled()) { closeQuietly(response); throw new IOException("Canceled"); } return response; } catch (IOException e) { calledNoMoreExchanges = true; throw transmitter.noMoreExchanges(e); } finally { if (!calledNoMoreExchanges) { transmitter.noMoreExchanges(null); } } }
( 2 ) 、异步 Request 请求
在 RealCall 的 enqueue 异步请求方法中 , 最终调用的还是 OkHttpClient 的 dispatcher 进行调度 ;
在上一篇博客 【OkHttp】OkHttp 源码分析 ( OkHttpClient.Builder 构造器源码分析 ) 已经提到过 OkHttpClient 的 Dispatcher dispatcher 成员 , 是 Get / Post 方法的请求线程调度器 ;
final class RealCall implements Call { final OkHttpClient client; @Override public void enqueue(Callback responseCallback) { synchronized (this) { if (executed) throw new IllegalStateException("Already Executed"); executed = true; } transmitter.callStart(); client.dispatcher().enqueue(new AsyncCall(responseCallback)); } }