Android开发Android技术知识程序员

OkHttp源码分析

2017-12-16  本文已影响60人  721d739b6619

前言

之前看过Retrofit的源码,Retrofit发送http请求最终是通过OkHttp为其完成的。如果对Retrofit源码不是很了解可以看这里Retrofit使用范例的源码分析

真正从这里开始

那么我们从Retrofit该框架作切入点,看看okhttp是如何发送请求的。
这里简单概括一下。

Retrofit通过OkHttp发送请求从这里出发

Retrofit.create(final Class<T> service)

image.png

大家都知道Retrofit是基于动态代理实现对发送http请求参数的封装。
而生成代理对象就要通过此类此方法为其实现:
Proxy.newProxyInstance方法


image.png

如果对以上不了解可以看看动态代理

关于Retrofit就说到这,今天重点是OkHttp。

从第一章截图可以看到:
创建了一个 OkHttpCall对象,而Retrofit发送http请求就是通过这个对象完成的。当然,如果不同Retrofit也可以自己构建这么一个对象完成通过OkHttp发送请求。

OkHttpCall为OkHttp请求入口

该类发送http请求其实就是两个方法:

我先拿其中一个来看,后面再说两者有什么不同;

enqueue(final Callback<T> callback)方法

直接将代码贴出来:

@Override public void enqueue(final Callback<T> callback) {
    if (callback == null) throw new NullPointerException("callback == null");

    okhttp3.Call call;
    Throwable failure;

    synchronized (this) {
      if (executed) throw new IllegalStateException("Already executed.");
      executed = true;

      call = rawCall;
      failure = creationFailure;
      if (call == null && failure == null) {
        try {
          call = rawCall = createRawCall();
        } catch (Throwable t) {
          failure = creationFailure = t;
        }
      }
    }

    if (failure != null) {
      callback.onFailure(this, failure);
      return;
    }

    if (canceled) {
      call.cancel();
    }

    call.enqueue(new okhttp3.Callback() {
      @Override public void onResponse(okhttp3.Call call, okhttp3.Response rawResponse)
          throws IOException {
        Response<T> response;
        try {
          response = parseResponse(rawResponse);
        } catch (Throwable e) {
          callFailure(e);
          return;
        }
        callSuccess(response);
      }

步骤如下:

如果可以看整个OkHttp发送请求就是这样了。但这就等于什么都没有说嘛。所以再看看在发送请求前,对于OkHttp对其添加一些参数,如添加header相关参数,打印日志等。基于这些,看看OkHttp里面的实现过程。

OkHttpClient封装

我们可以基于OkHttpClient封装诸如这些参数:


image.png

这里就会有个疑问,到底这些参数是怎么样被调用的。
往下看...

RealCall

在上面不管是调用enqueue()或execute()的时候,会调用createRawCall();获得call对象。

image.png
image.png
在serviceMethod.callFactory这个参数其实就是OkHttpClient
在封装Retrofit对象中会传入OkHttpClient;
image.png
既然知道callFactory是OkHttpClient那么就可以看看newCall(request)方法:
image.png

细看RealCall对象:

核心就这么两行代码:

client.dispatcher().executed(this);
Response result = getResponseWithInterceptorChain();

client.dispatcher()是什么

其实点击一下就会看到Dispatcher这个类的作用是什么了。


image.png
image.png

上面两图是在Dispatcher发现的。
基本上看完这里会发现execute()和enqueue()有什么不同。

getResponseWithInterceptorChain();

image.png
这里可以看到将所有的拦截器都放在List集合上。
创建了一个RealInterceptorChain对象,执行其proceed(originalRequest)方法。
其实这里就是整个OkHttp的核心了。

RealInterceptorChain的proceed()方法,递归执行每个Interceptor的intercept(next);

这里标题都说明得很清楚,执行每个Interceptor。而自定义的Interceptor都会放在前面被先执行。下面我们看看每个Interceptor的作用。

RetryAndFollowUpInterceptor

该拦截器从失败中恢复和必要时有重定向。 如果call被取消就会抛出IO异常
上面是该类的官方解释。简单来说该Interceptor如果第一次发送请求他没有做什么事情。更多是请求发送失败重试中用到。

BridgeInterceptor

该Interceptor主要做的就是将从传入来的Request请求头封装成网络发送http的规范请求头:


BridgeInterceptor的intercept()方法的部分截图.png

这里其实你还会看到OkHttp默认情况下是要求服务端返回的数据进行gzip压缩。然后OkHttp会将返回的数据解压。


image.png
image.png

CacheInterceptor

看名字就应该知道这个Interceptor是干什么的。其实就是缓存用的。

ConnectInterceptor

该ConnectInterceptor就是连接目标服务器的:


image.png
基于http1.1发送请求.png

上面截图将三种超时的时间设置了。

socket连接在RealConnection的connect()方法

在上面截图中其实有个方法是findHealthyConnection(connectTimeout, readTimeout,
writeTimeout, connectionRetryEnabled, doExtensiveHealthChecks);
就是下面截图中核心的执行过程。

image.png
buildConnection()方法
image.png
看到这里有个地方可以说,如果是http请求其实设置writeTimeout是没有任何意义的。在http或https请求是没有用到这个参数的。这里也反映了OkHttp请求不单单是基于http1.X请求还有websocket和SPY和http2.0都可以的。
最终socket连接其实是AndroidPlatform.connectSocket()
image.png

总结下:

CallServerInterceptor

CallServerInterceptor的intercept()方法:

整个OkHttp的http请求就是这样。这里输入输出流OkHttp是用Okio,也是它自家公司的一个开源项目。

上一篇 下一篇

猜你喜欢

热点阅读