Okhttp3源码分析之一

一、OKHTTP简介

OKHttp是一个处理网络请求的开源项目OKHttp GitHub地址

OKHttp优点

  1. 支持HTTP2/SPDY(SPDY是Google开发的基于TCP的传输层协议,用以最小化网络延迟,提升网络速度,优化用户的网络使用体验。)
  2. socket自动选择最好路线,并支持自动重连,拥有自动维护的socket连接池,减少握手次数,减少了请求延迟,共享Socket,减少对服务器的请求次数。
  3. 基于Headers的缓存策略减少重复的网络请求。
  4. 拥有Interceptors轻松处理请求与响应(自动处理GZip压缩)。

OKHttp的功能

  1. PUT,DELETE,POST,GET等请求
  2. 文件的上传下载
  3. 加载图片(内部会图片大小自动压缩)
  4. 支持请求回调,直接返回对象、对象集合
  5. 支持session的保持

二、OkHttp使用

此处只举例异步调用:

        //1.创建OkHttpClient对象
        OkHttpClient okHttpClient = new OkHttpClient();
        //2.创建Request对象,设置一个url地址(百度地址),设置请求方式。
        Request request = new Request.Builder().url("http://www.baidu.com").method("GET",null).build();
        //3.创建一个call对象,参数就是Request请求对象
        Call call = okHttpClient.newCall(request);
        //4.请求加入调度,重写回调方法
        call.enqueue(new Callback() {
            //请求失败执行的方法
            @Override
            public void onFailure(Call call, IOException e) {
            }
            //请求成功执行的方法
            @Override
            public void onResponse(Call call, Response response) throws IOException {
            }
        });

上面就是发送一个异步GET请求的4个步骤:

  1. 创建OkHttpClient对象
  2. 通过Builder模式创建Request对象,参数必须有个url参数,可以通过Request.Builder设置更多的参数比如:header、method等
  3. 通过request的对象去构造得到一个Call对象,Call对象有execute()和cancel()等方法。
  4. 以异步的方式去执行请求,调用的是call.enqueue,将call加入调度队列,任务执行完成会在Callback中得到结果。

注意事项:

  1. 异步调用的回调函数是在子线程,我们不能在子线程更新UI,需要借助于 runOnUiThread() 方法或者 Handler 来处理。
  2. onResponse回调有一个参数是response,如果我们想获得返回的是字符串,可以通过response.body().string()获取;如果希望获得返回的二进制字节数组,则调用response.body().bytes();如果你想拿到返回的inputStream,则调response.body().byteStream(),有inputStream我们就可以通过IO的方式写文件

三、OkHttpClient源码分析

1、先看内部类和构造函数的实现

public class OkHttpClient implements Cloneable, Call.Factory, WebSocket.Factory {
  //协议,支持http2和http1
  static final List<Protocol> DEFAULT_PROTOCOLS = Util.immutableList(
      Protocol.HTTP_2, Protocol.HTTP_1_1);

  //连接规范,带有扩展的现代TLS连接 和 未加密、未经身份验证的连接
  //具体作用先不看
  static final List<ConnectionSpec> DEFAULT_CONNECTION_SPECS = Util.immutableList(
      ConnectionSpec.MODERN_TLS, ConnectionSpec.CLEARTEXT);

  static {
    Internal.instance = new Internal() {
       //加入请求头
      @Override public void addLenient(Headers.Builder builder, String line) {
        builder.addLenient(line);
      }
        //加入请求头
      @Override public void addLenient(Headers.Builder builder, String name, String value) {
        builder.addLenient(name, value);
      }

        //设置缓存
      @Override public void setCache(OkHttpClient.Builder builder, InternalCache internalCache) {
        builder.setInternalCache(internalCache);
      }

       //连接置空闲,两个参数ConnectionPool(连接池),RealConnection(真实连接)
       //在连接池把真实连接置为空闲状态
      @Override public boolean connectionBecameIdle(
          ConnectionPool pool, RealConnection connection) {
        return pool.connectionBecameIdle(connection);
      }

       //获取真实连接,通过address(地址)、StreamAllocation(流分配)、Route (线路)
       //在连接池获取当前真实连接
      @Override public RealConnection get(ConnectionPool pool, Address address,
          StreamAllocation streamAllocation, Route route) {
        return pool.get(address, streamAllocation, route);
      }

       //判断两个主机是否相同
      @Override public boolean equalsNonHost(Address a, Address b) {
        return a.equalsNonHost(b);
      }

      //消除重复连接
      @Override public Socket deduplicate(
          ConnectionPool pool, Address address, StreamAllocation streamAllocation) {
        return pool.deduplicate(address, streamAllocation);
      }

        //加入连接池
      @Override public void put(ConnectionPool pool, RealConnection connection) {
        pool.put(connection);
      }

        //线路集合
      @Override public RouteDatabase routeDatabase(ConnectionPool connectionPool) {
        return connectionPool.routeDatabase;
      }

       //响应状态码
      @Override public int code(Response.Builder responseBuilder) {
        return responseBuilder.code;
      }

       //
      @Override
      public void apply(ConnectionSpec tlsConfiguration, SSLSocket sslSocket, boolean isFallback) {
        tlsConfiguration.apply(sslSocket, isFallback);
      }

        //无效地址
      @Override public boolean isInvalidHttpUrlHost(IllegalArgumentException e) {
        return e.getMessage().startsWith(HttpUrl.Builder.INVALID_HOST);
      }

       //流分配
      @Override public StreamAllocation streamAllocation(Call call) {
        return ((RealCall) call).streamAllocation();
      }

        //异常
      @Override public @Nullable IOException timeoutExit(Call call, @Nullable IOException e) {
        return ((RealCall) call).timeoutExit(e);
      }

        //创建新的call
      @Override public Call newWebSocketCall(OkHttpClient client, Request originalRequest) {
        return RealCall.newRealCall(client, originalRequest, true);
      }
    };
  }

 final Dispatcher dispatcher;//任务调度,执行异步请求时的策略
  final @Nullable Proxy proxy;//代理
  final List<Protocol> protocols;//所支持的协议
  final List<ConnectionSpec> connectionSpecs;//连接规范
  final List<Interceptor> interceptors;//拦截器
  final List<Interceptor> networkInterceptors;//网络拦截器
  final EventListener.Factory eventListenerFactory;//负责监听整个连接请求的生命周期
  final ProxySelector proxySelector;//代理选择器
  final CookieJar cookieJar;//cookie缓存
  final @Nullable Cache cache;//响应报文缓存
  final @Nullable InternalCache internalCache;//OKhttp内部缓存
  final SocketFactory socketFactory;//创建socket的工厂
  final SSLSocketFactory sslSocketFactory;//ssl的socket工厂继承于SocketFactory 
  final CertificateChainCleaner certificateChainCleaner;//证书的获取和清除
  final HostnameVerifier hostnameVerifier;//主机认证
  final CertificatePinner certificatePinner;//该类用于约束哪些证书是可信的。 锁定证书可以防止对证书颁发机构相关的攻击。 它还阻止通过用户已知或未知的中间证书颁发机构建立的连接
  final Authenticator proxyAuthenticator;//认证器
  final Authenticator authenticator;//
  final ConnectionPool connectionPool;//连接池
  final Dns dns;//dns获取ip,OKHTTP尝试的顺序排列。如果与地址的连接失败,OKHTTP将重试与下一个地址的连接,直到要么建立连接,要么耗尽IP地址集,要么超过限制
  final boolean followSslRedirects;//遵循SSL重定向
  final boolean followRedirects;//遵循重定向
  final boolean retryOnConnectionFailure;//重试连接失败
  final int callTimeout;//请求超时
  final int connectTimeout;//连接超时
  final int readTimeout;//读超时
  final int writeTimeout;//写超时
  final int pingInterval;//ping 间隔时长

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

  OkHttpClient(Builder builder) {
    this.dispatcher = builder.dispatcher;
    this.proxy = builder.proxy;
    this.protocols = builder.protocols;
    this.connectionSpecs = builder.connectionSpecs;
    this.interceptors = Util.immutableList(builder.interceptors);
    this.networkInterceptors = Util.immutableList(builder.networkInterceptors);
    this.eventListenerFactory = builder.eventListenerFactory;
    this.proxySelector = builder.proxySelector;
    this.cookieJar = builder.cookieJar;
    this.cache = builder.cache;
    this.internalCache = builder.internalCache;
    this.socketFactory = builder.socketFactory;

    boolean isTLS = false;
    for (ConnectionSpec spec : connectionSpecs) {
      isTLS = isTLS || spec.isTls();
    }

    if (builder.sslSocketFactory != null || !isTLS) {
      this.sslSocketFactory = builder.sslSocketFactory;
      this.certificateChainCleaner = builder.certificateChainCleaner;
    } else {
      X509TrustManager trustManager = Util.platformTrustManager();
      this.sslSocketFactory = newSslSocketFactory(trustManager);
      this.certificateChainCleaner = CertificateChainCleaner.get(trustManager);
    }

    if (sslSocketFactory != null) {
      Platform.get().configureSslSocketFactory(sslSocketFactory);
    }

    this.hostnameVerifier = builder.hostnameVerifier;
    this.certificatePinner = builder.certificatePinner.withCertificateChainCleaner(
        certificateChainCleaner);
    this.proxyAuthenticator = builder.proxyAuthenticator;
    this.authenticator = builder.authenticator;
    this.connectionPool = builder.connectionPool;
    this.dns = builder.dns;
    this.followSslRedirects = builder.followSslRedirects;
    this.followRedirects = builder.followRedirects;
    this.retryOnConnectionFailure = builder.retryOnConnectionFailure;
    this.callTimeout = builder.callTimeout;
    this.connectTimeout = builder.connectTimeout;
    this.readTimeout = builder.readTimeout;
    this.writeTimeout = builder.writeTimeout;
    this.pingInterval = builder.pingInterval;

    if (interceptors.contains(null)) {
      throw new IllegalStateException("Null interceptor: " + interceptors);
    }
    if (networkInterceptors.contains(null)) {
      throw new IllegalStateException("Null network interceptor: " + networkInterceptors);
    }
  }

Okhttp3源码分析之二

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值