文章目录
前言 Okhttp是目前主流的网络请求框架, 我们不仅仅会用框架,而且还得知道框架的具体实现。学习完框架后写下此篇学习笔记
阅读本文前须知: 本文篇幅较长,设计内容很多,请收藏在空余时间阅读全文
1. HttpClient与HttpUrlConnection的区别
简而言之:就是Volley的的请求方式(API2.3之前用的httpClient 2.3之后用的HttpUrlconnection)
httpclient 和httpUrlConnection都支持https协议, 都是以流的形式进行传输数据.支持IPv6以及连接池等功能.
httpclient拥有很多API 保证它的兼容性进行拓展很难,google在6.0的时候废弃Httpclient AS想用这个类可以使用:org.apach.http.legacy
HttpUrlConnection:轻量级,API较少,易拓展,满足大部分的android数据传输 .例如Volley框架
2. OKHttp源码分析
-
使用步骤:
首先创建OKhttpClient对象, —>再创建一个 request请求 ,给request添加url,header请求方式等参数, 用OKhttpclient.newCall方法返回一个call对象.同步方法: call.execute()来请求数据,异步:call.euque();首先创建OKhttpClient对象, 再创建一个 request请求 ,给request添加url,header请求方式等参数, 用OKhttpclient.newCall方法返回一个call对象.同步方法: call.execute()来请求数据,异步:call.euque();
Request request = new Request.Builder().post(requestBody).url(url).build(); //得到一个request请求 OkHttpClient okHttpClient = new OkHttpClient(); //得到OKHttpClient对象 Call call = okHttpClient.newCall(request); //得到一个call call.enqueue(new Callback()); //异步 // call.call.execute();//同步 // call.request().body()//得到返回体
-
dispatcher任务调度器, (后面有详细说明)
- 它定义了三个双向任务队列,二个异步队列:runningAsyncCalls和readyASyncCalls和一个运行在同步请求的runningSyncCalls队列
- 一个标准线程池 executorServic 无界线程池,60s回收,用于大量耗时较短的异步任务
-
Request请求
-
Request的builder方法默认请求方式为GET和请求的Url
-
通过OKhttpclient和request构造一个call对象,它的实现时realCall
public Call newCall(Request request) { return RealCall.newRealCall(this, request, false /* for web socket */); } static RealCall newRealCall(OkHttpClient client, Request originalRequest, boolean forWebSocket){ // Safely publish the Call instance to the EventListener. RealCall call = new RealCall(client, originalRequest, forWebSocket); call.eventListener = client.eventListenerFactory().create(call); return call; } private RealCall(OkHttpClient client, Request originalRequest, boolean forWebSocket) { this.client = client; this.originalRequest = originalRequest; this.forWebSocket = forWebSocket; this.retryAndFollowUpInterceptor = new RetryAndFollowUpInterceptor(client, forWebSocket); }
-
在realCall中构造了一个RetryAndFollowUpInterceptor拦截器用于处理请求错误和重定向等,这个是Okhttp框架精髓 interceptor chain中的一环, 默认情况下的第一个拦截器,除非调用OKhttpclient.builder.addInterceptor来添加全局拦截器,在RealCall.getResponseWithInterceptorChain()中添加默认的5个拦截器
-
RealCall
-
enque(callBack方法)
// RealCall.java public void enqueue(Callback responseCallback) { synchronized (this) { //每个请求只能之执行一次 if (executed) throw new IllegalStateException("Already Executed"); executed = true; } captureCallStackTrace(); eventListener.callStart(this); client.dispatcher().enqueue(new AsyncCall(responseCallback)); }
-
一个call只能执行一次,否则会出现异常,这里创建一个AsyncCall并将CallBack穿入,接着交给任务分发器Dispatcher来处理
// dispatcher.java synchronized void enqueue(AsyncCall call) { //正在执行的任务数量小于最大值(64),并且此任务所属主机的正在执行任务小于最大值(5) if (runningAsyncCalls.size() < maxRequests && runningCallsForHost(call) < maxRequestsPerHost) { runningAsyncCalls.add(call); executorService().execute(call); } else { readyAsyncCalls.add(call); } }
-
从dispatcher的enqueue方法看出,对于入队做了限制,dispatcher类定义了请求数量的最大值为64个,请求的主机正再执行任务小于5台,满足以上要求的线程就可以加入队列,通过线程池执行该任务,否则加入readyAsyncCalls线程池中等待.
-
-
AsyncCall
-
它继承于NameRunnable 而NameRunnable实现runnable接口. 作用1. 采用模板方法的设计模式,让子类具体操作放在execute()中, 作用2. 给线程指定一个名称
@Override protected void execute() { boolean signalledCallback = false; try { //调用 getResponseWithInterceptorChain()获得响应内容 Response response = getResponseWithInterceptorChain(); //① if (retryAndFollowUpInterceptor.isCanceled()) { //这个标记为主要是避免异常时2次回调 signalledCallback = true; //回调Callback告知失败 responseCallback.onFailure(RealCall.this, new IOException("Canceled")); } else { signalledCallback = true; //回调Callback,将响应内容传回去 responseCallback.onResponse(RealCall.this, response); } } catch (IOException e) { if (signalledCallback) { // Do not signal the callback twice! Platform.get().log(INFO, "Callback failure for " + toLoggableString(), e); } else { eventListener.callFailed(RealCall.this, e); responseCallback.onFailure(RealCall.this, e); } } finally { //不管请求成功与否,都进行finished()操作 client.dispatcher().finished(this);//② } }
-
client.dispatcher().finished(this)方法
private void promoteCalls() { if (runningAsyncCalls.size() >= maxRequests) return; // Already running max capacity. if (readyAsyncCalls.isEmpty()) return; // No ready calls to promote. //若条件允许,将readyAsyncCalls中的任务移动到runningAsyncCalls中,并交给线程池执行 for (Iterator<AsyncCall> i = readyAsyncCalls.iterator(); i.hasNext(); ) { AsyncCall call = i.next(); if (runningCallsForHost(call) < maxRequestsPerHost) { i.remove(); runningAsyncCalls.add(call); executorService().execute(call); } //当runningAsyncCalls满了,直接退出迭代 if (runningAsyncCalls.size() >= maxRequests) return; // Reached max capacity. } }
-
promoteCalls方法推动了下个任务的执行,逻辑: 判断正在请求的队列是否大于64个,判断正在准备的队列是否为空,若条件满足, readyAsyncCall的任务移动到runningAsyncCalls中,并且交给线程池去执行
-
-
interceptorChain
-
重点就是interceptors这个集合,1. 是将前面用户自己创建的拦截器,2.添加retryAndFollowUpInterceptor错误重定向拦截器,3. 添加桥接拦截器4.缓存拦截器5.接连拦截器6.网络拦截器 最后通过RealInterceptorChain#proceed(Request)来执行interceptor chain
Response getResponseWithInterceptorChain() throws IOException { // Build a full stack of interceptors. List<Interceptor> interceptors = new ArrayList<>(); //这是一个List,是有序的 interceptors.addAll(client.interceptors());//首先添加的是用户添加的全局拦截器 interceptors.add
-
-