简介
OkOne是一款基于okhttp库的网络性能优化框架,但不同于其他框架对okhttp的使用调用进行封装,而是从不一样的方面,以对开发者无侵入的方式进行优化。
更多介绍见《OkOne-基于okhttp的网络性能优化框架》
GitHub地址
https://github.com/chidehang/OkOne
预建连
开发者可以在合适的时机提前建立连接,若连接成功,则会将其添加进okhttp连接池。
OkOne.preBuildConnection(okHttpClient, url, new PreConnectCallback() {
@Override
public void connectCompleted(String url) {
Log.d(TAG, "预建连成功: " + url);
}
@Override
public void connectFailed(Throwable t) {
Log.e(TAG, "预建连失败", t);
}
});
效果演示
- 首次尝试预建连
预连接 “https://stackoverflow.com/” ,连接成功。
- 重复预建连
尝试再次对 “https://stackoverflow.com/” 域名预建连,会直接返回错误,避免重复预建连。
- 接口请求
请求 “https://stackoverflow.com/” 响应成功,可以看到从callStart直接到connectionAcquired,省去了中间的DNS和握手建连过程。
原理剖析
OkHttp框架本身不对开发者开放预建连功能,要实现预建连功能必须了解OkHttp中的Connection(连接)创建和ConnectionPool(连接池)机制。接下来深入OkHttp框架源码中进行分析,找到实现预建连的插入点。
源码基于OkHttp当前最新版本4.9.0
大家都知道OkHttp在发起请求后,会经过拦截链层层处理,其中ConnectInterceptor拦截器负责查找或新建Connection。
ConnectInterceptor#intercept -> RealCall#initExchange -> ExchangeFinder#find
ConnectInterceptor中是通过ExchangeFinder的find方法来获取Connection,直接来看ExchangeFinder#find方法。
fun find(
client: OkHttpClient,
chain: RealInterceptorChain
): ExchangeCodec {
try {
// 进一步获取可用Connection
val resultConnection = findHealthyConnection(
// ···限于篇幅省略参数代码
)
return resultConnection.newCodec(client, chain)
} catch (e: RouteException) {
// ···
} catch (e: IOException) {
// ···
}
}
接着看ExchangeFinder#findHealthyConnection:
@Throws(IOException::class)
private fun findHealthyConnection(
connectTimeout: Int,
readTimeout: Int,
writeTimeout: Int,
pingIntervalMillis: Int,
connectionRetryEnabled: Boolean,
doExtensiveHealthChecks: Boolean
): RealConnection {
while (true) {