Okhttp源码实例详解

阅读分析

在阅读本篇文章时,请对比Okhttp源码。基于3.6版本Okhttp.

Okhttp使用实例

            //创建client
            OkHttpClient client = new OkHttpClient();
            //创建request请求
            Request request = new Request.Builder().url("http://www.baidu.com") .build();
            //发起请求
            try {
                Response response = client.newCall(request).execute();
                if (response.isSuccessful()) {
                    System.out.println("成功");
                }
            } catch (IOException e) {
                e.printStackTrace();
            }

创建Okhttp实例对象

public OkHttpClient() {
   this(new Builder()); 
 }
OkHttpClient(Builder builder) {
//网络请求调度器
this.dispatcher = builder.dispatcher;
this.proxy = builder.proxy;
//默认支持的Http协议版本
this.protocols = builder.protocols;
......//省略代码
}  }

创建Okhttp实例时使用了建造者模式.在创造Okhttp实例对象时,Okhttp配置了很多的参数,dispather任务调度器等

创建Request对象

Request也使用了建造者模式,里面配置了请求的header body method url。

创建Call

调用client.newCall(request);时最终会调用RealCall里面的newCall方法。
RealCall是Call的实现类。RealCall构造方法中创造了重定向拦截器。返回一个RealCall实例

发起请求

同步请求execute()

       @Override 
       public Response execute() throws IOException {
           synchronized (this) {
           //判断同步请求是否执行过,如果执行过抛出异常
           if (executed) throw new IllegalStateException("Already Executed");
           executed = true;
           }
         captureCallStackTrace();
         //打开监听事件
         eventListener.callStart(this);
         try {
         //将请求添加到任务队列
          client.dispatcher().executed(this);
          //通过拦截器发起请求
          Response result = getResponseWithInterceptorChain();
          if (result == null) throw new IOException("Canceled");
           return result;
          } catch (IOException e) {
           eventListener.callFailed(this, e);
           throw e;
           } finally {
           //结束请求
           client.dispatcher().finished(this);
       }
    }

异步请求enqueen()

@Override
public void enqueue(Callback responseCallback) {
synchronized (this) {
  if (executed) throw new IllegalStateException("Already Executed");
  executed = true;
}
captureCallStackTrace();
eventListener.callStart(this);
//创建AsyncCall,最终异步请求回调会在AsyncCall中执行
client.dispatcher().enqueue(new AsyncCall(responseCallback));
 }

任务调度器Dispatcher

synchronized void enqueue(AsyncCall call) {
//判断异步请求个数是否小于最大个数,同一个host的请求个数是否小于最大允许个数
if (runningAsyncCalls.size() < maxRequests && runningCallsForHost(call) < maxRequestsPerHost) {
  //将请求添加到异步请求队列
  runningAsyncCalls.add(call);
  //获取一个线程池,执行call的回调,最终在RealCall的AsyncCall的run方法中执行真正的回调请求。
  //在execute方法中执行getWritewithResponse 通过拦截器链发起请求
  executorService().execute(call);
} else {
//将请求添加到异步等待队列
  readyAsyncCalls.add(call);
}
}

任务调度器里面定义了最大请求数和同一个host允许的最大请求数。
管理了三个队列
readyAsyncCalls 等待被执行的异步请求队列
runningAsynCalls 正在执行的异步请求队列
runningSyncCalls 正在运行的同步请求队列,同步请求会将请求直接添加在队列中。
实现多线程调度并发:
1 dispatcher内部创建了一个线程池。类似缓存线程,如果当前线程池饱和回调用addWorker(command, false)创建新的线程,
所以实际上并发策略是通过dispatcher来实现
2调度策略。
1:设置了最大的线程数,和同一个host下的最大数
2: 等待队列中的请求什么时候执行。在AsyncCalls执行结束会执行dispatcher方法,最终会遍历等待队列,如果运行队列符合
小于64并且host小于5,等待队列不为空,将请求从等待队列中移除,调用线程池的executorService().execute(call);的方法。

拦截器

//Okhttp通过拦截器链发起请求
Response getResponseWithInterceptorChain() throws IOException {
// 创建拦截器集合
List<Interceptor> interceptors = new ArrayList<>();
//自定义拦截器
interceptors.addAll(client.interceptors());
//重定向拦截器
interceptors.add(retryAndFollowUpInterceptor);
//桥接连接器
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, null, null, null, 0,
    originalRequest, this, eventListener, client.connectTimeoutMillis(),
    client.readTimeoutMillis(), client.writeTimeoutMillis());
//开启链式调用,通过proceed方法一次调用每一个拦截器。
return chain.proceed(originalRequest);

}

重定向拦截器retryAndFollowUpInterceptor

重定向流程:通过flowwUp根据响应吗处理Request请求,如果request为空返回Reponse.不为空则进行重定向。

桥接连接器BridgeInterInterceptor

将用户请求request转换为可以进行网络访问的请求。设置内容的长度,cookie,编码方式,请求头等相关信息。
调用procced方法将请求传递给下一个拦截器。将response返回给上一个拦截器

CacheInterceptor缓存拦截器

1缓存拦截器,需要穿进去一个缓存策略。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值