Okhttp源码学习之总体流程

这个库一直想要去学习,不过一直没有时间去做,打算一点点梳理Okhttp。本文将按照发起网络请求的顺序来详细描述下okhttp是如何发起网络请求的,其中包含一些优秀文章可供大家参考。

使用实例

先放一段Okhttp的使用代码。

       //1
        OkHttpClient client=new OkHttpClient();
        //2
        Request request = new Request.Builder()
        .url("url)
        .build();
        //3
		client.newCall(request).enqueue(new Callback() {
   
    		@Override
    		public void onFailure(Call call, IOException e) {
   
        		e.printStackTrace();
    		}
    		@Override
    		public void onResponse(Call call, Response response) throws IOException {
   
    			String results = response.body().string(); 
    		}
		}); 

我们阅读源码就要从暴露给用户使用的那个类先去入手,对应Okhttp就是**(创建)OkhttpClient**,以及RequestCallback,在新写Callback的时候要重写onFailure(Call call, IOException e)OnResponse(Call call, Response response)两个函数,于是另一个重要的类Response类简单来说,使用的时候,只需要传入网络的url地址,然后加上新创建的Callback对象(包括重写两个函数)就完成了对url地址的访问(获取数据或上传数据)。

整体流程

1.创建OkhttpClient实例

在读源码之前,每个类都会有一些注释,先阅读下注释。

1.1 用户使用时,创建全局(单例)实例

这里的意思就是说,最好在整个应用中只包含一个(全局)OkhttpClient实例,在每一个发起Http请求的时候重用该实例即可(单例),同时复用的还有Response缓存、共用线程池以及共用连接池。

 * <h3>OkHttpClients should be shared</h3>
 *
 * <p>OkHttp performs best when you create a single {
   @code OkHttpClient} instance and reuse it for
 * all of your HTTP calls. This is because each client holds its own connection pool and thread
 * pools. Reusing connections and threads reduces latency and saves memory. Conversely, creating a
 * client for each request wastes resources on idle pools.

1.2 构造方式

可以使用两种方式创建OkHttpClient的实例(构造函数和使用Builder),以及一种特殊的构造方式。
还是先看注释。

<p>Use {
   @code new OkHttpClient()} to create a shared instance with the default settings:
 * <pre>   {
   @code
 *
 *   // The singleton HTTP client.
 *   public final OkHttpClient client = new OkHttpClient();
 * }</pre>
 *
 * <p>Or use {
   @code new OkHttpClient.Builder()} to create a shared instance with custom settings:
 * <pre>   {
   @code
 *
 *   // The singleton HTTP client.
 *   public final OkHttpClient client = new OkHttpClient.Builder()
 *       .addInterceptor(new HttpLoggingInterceptor())
 *       .cache(new Cache(cacheDir, cacheSize))
 *       .build();
 * }</pre>

我们来读源码。
这是第一种默认的方式

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

最后会调用该函数,使用的就是默认的Builder

private OkHttpClient(Builder builder) {
   
	this.dispatcher = builder.dispatcher;
    this.proxy = builder.proxy;
    this.protocols = builder.protocols;
    this.connectionSpecs = builder.connectionSpecs;
    ...
}

第二种方式:想要配置OkhttpClient的一些参数,就需要使用Builder。

public final OkHttpClient client = new OkHttpClient.Builder()
        .addInterceptor(new HttpLoggingInterceptor())
        .cache(new Cache(cacheDir, cacheSize))
        ...//其他设置
        .build();

最后调用Builder类内的build函数,这里的this就是Builder,所以会调用OkhttpClient(Builder builder)来更改client的数据域。

 public OkHttpClient build() {
   
      return new OkHttpClient(this);
    }

总结:OkHttpClient本身不能设置参数,需要借助于其内部类Builder设置参数,参数设置完成后,调用Builder的build方法得到一个配置好参数的OkHttpClient对象。这些配置的参数会对该OkHttpClient对象所生成的所有HTTP请求都有影响。
第三种方式:我们先看注释中的文字。
您可以使用{@link#NewBuilder()}自定义共享的OkHttpClient实例。 这将构建一个共享相同连接池,线程池和配置的客户端。 使用生成器方法为特定目的配置派生客户端。
共享相同连接池,线程池和配置的客户端,共享谁的呢?当然是共享那个client实例的。有时候我们想单独给某个网络请求设置特别的几个参数,比如只想设置某个请求的超时时间,但是还想保持OkHttpClient对象(client)中的其他的参数设置,那么可以调用OkHttpClient对象的newBuilder()方法。

* <h3>Customize your client with newBuilder()</h3>
 *
 * <p>You can customize a shared OkHttpClient instance with {
   @link #newBuilder()}. This builds a
 * client that shares the same connection pool, thread pools, and configuration. Use the builder
 * methods to configure the derived client for a specific purpose.
 *
 * <p>This example shows a call with a short 500 millisecond timeout: <pre>   {
   @code
 *
 *   OkHttpClient eagerClient = client.newBuilder()
 *       .readTimeout(500, TimeUnit.MILLISECONDS)
 *       .build();
 *   Response response = eagerClient.newCall(request).execute();
 * }</pre>

这里的this是Okhttp的实例

public Builder newBuilder() {
   
    return new Builder(this);
  }

之后会调用Builder类中的这个构造函数,这样就在builder中保存了OkHttpClient中的参数。

 Builder(OkHttpClient okHttpClient) {
   
      this.dispatcher = okHttpClient.dispatcher;
      this.proxy = okHttpClient.proxy;
      this.protocols = okHttpClient.protocols;
      this.connectionSpecs = okHttpClient.connectionSpecs;
      ...
    }

1.3 优点

不需要将其杀掉。
保持空闲的线程和连接将自动释放。

<h3>Shutdown isn't necessary</h3>

1.4 涉及的模式

1.构造者模式

不用说了,都有builder了,肯定就是构造者模式了。

2.单例模式

有点单例模式的意思,但这里没有,就是我们构建的OkhttpCilent最好要单例,只构造一个来复用。

3.外观模式

用户可以使用这个类来进行一些操作来实现内部的功能。

2.构造Request对象

构造方法

Request也是需要通过构造者模式来构造。

private Request(Builder builder
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值