Okhttp3使用 + 源码完全解析
2017-09-21 20:09
302 查看
在使用过okhttp3之后,必然的一步当是对源码的研究 这样可以对其优劣和功能封装有一个全面详尽的了解
ok 下面粘贴okhttp3的核心代码(url暂时随意定义)
下面进入正题,来对源码进行分析
首先来看okhttp初始化实例
1.1 //OkHttpClient okHttpClient = new OkHttpClient();
其实就是初始化对象 和属性的相关配置过程
1.2Requst的初始化
下面来看其源码:
到这里准备工作就完成了
下面来从请求开始详细看源码(以上比较简单 没有什么可以讲的)
okhttp3创建请求的主体call对象 其实返回的是一个realCall的实例化对象,并完成一系列的相关初始化配置;
下面来看请求
//call.enqueue
由以上代码 可以看出来 okhttp的请求是由dispatcher来完成的;而dispatcher又是什么呢 ?
其实是一个网络的任务调度器;
那么下面来看下调度器的实现.
Dispatcher主要用于控制并发 并且维护了一部分变量
在请求之前dispatcher会自己创建线程池
当然也可以有程序员自己来创建线程池
ok~初步了解调度器之后来看异步请求的源码
在调度器的enqueue中会先判断当前最大请求数和当前最大主机请求数 如果不超过默认的最大值 则吧请求加入到正在运行的请求队列—->runningAsyncCalls;
否则会加入到将要运行的请求队列中进行等待—->readyAsyncCalls
然后 executorService().execute(call);开始运行传入的线程 即传入的AsyncCall;而AsyncCall作为RealCall的内部实现类 会走execute;
ok下面来看AsyncCall–>execute ,在这里 开始进行网络请求:
在上面代码中不难看出走了一系列方法 来进行网络请求 为了方便读者理解 先来看finally下的方法 (这个方法必然会走到的):
直接提取关键代码:
finished—->if (promoteCalls) promoteCalls(); 当请求完之后 promoteCalls为true 则会走promoteCalls() ;从上面代码中可图看出来promoteCalls()中用迭代器遍历readyAsyncCalls 然后加入到runningAsyncCalls
其实就是在请求完成后 来请求缓存池中的线程
那么继续回头看AsyncCall–>execute中的逻辑,在这之前先简单介绍一下拦截器 okhttp中请求有用到拦截器
继续回到代码:AsyncCall–>execute:
上面代码中关键的请求代码是:
下面我们来看见其源码:
在上面代码中:
其实是初始化了拦截器 传参为读取/请求超时等….
实际请求的代码是:chain.proceed(originalRequest);
在拦截器拦截过程中,当存在多个拦截器,需要拦截等待,即第一个请求完下一个请求;其中拦截的代码会在上面代码中:
而真正请求的代码是//getResponse(request, forWebSocket);
那么接着来看它的源码:
到这里okhttp3的源码就解析完毕了 感谢支持 希望可以帮到你们~
ok 下面粘贴okhttp3的核心代码(url暂时随意定义)
OkHttpClient okHttpClient = new OkHttpClient(); Request request = new Request.Builder() .url("www.baidu.com") .build(); Call call = okHttpClient.newCall(request); call.enqueue(new Callback() { @Override public void onFailure(Call call, IOException e) { } @Override public void onResponse(Call call, Response response) throws IOException { } });
下面进入正题,来对源码进行分析
1.okhttp实例 和Request实例和配置
相当于初始化实例 比较简单首先来看okhttp初始化实例
1.1 //OkHttpClient okHttpClient = new OkHttpClient();
public OkHttpClient() { this(new Builder()); } public Builder() { dispatcher = new Dispatcher(); protocols = DEFAULT_PROTOCOLS; connectionSpecs = DEFAULT_CONNECTION_SPECS; eventListenerFactory = EventListener.factory(EventListener.NONE); proxySelector = ProxySelector.getDefault(); cookieJar = CookieJar.NO_COOKIES; socketFactory = SocketFactory.getDefault(); hostnameVerifier = OkHostnameVerifier.INSTANCE; certificatePinner = CertificatePinner.DEFAULT; proxyAuthenticator = Authenticator.NONE; authenticator = Authenticator.NONE; connectionPool = new ConnectionPool(); dns = Dns.SYSTEM; followSslRedirects = true; followRedirects = true; retryOnConnectionFailure = true; connectTimeout = 10_000; readTimeout = 10_000; writeTimeout = 10_000; pingInterval = 0; }
其实就是初始化对象 和属性的相关配置过程
1.2Requst的初始化
Request request = new Request.Builder() .url("www.baidu.com") .build();
下面来看其源码:
public Builder() { this.method = "GET"; this.headers = new Headers.Builder(); } public Builder url(String url) { if (url == null) throw new NullPointerException("url 4000 == null"); // Silently replace web socket URLs with HTTP URLs. if (url.regionMatches(true, 0, "ws:", 0, 3)) { url = "http:" + url.substring(3); } else if (url.regionMatches(true, 0, "wss:", 0, 4)) { url = "https:" + url.substring(4); } HttpUrl parsed = HttpUrl.parse(url); if (parsed == null) throw new IllegalArgumentException("unexpected url: " + url); return url(parsed); } public Request build() { if (url == null) throw new IllegalStateException("url == null"); return new Request(this); }
到这里准备工作就完成了
下面来从请求开始详细看源码(以上比较简单 没有什么可以讲的)
2.请求处理
//Call call = okHttpClient.newCall(request);@Override 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; }
okhttp3创建请求的主体call对象 其实返回的是一个realCall的实例化对象,并完成一系列的相关初始化配置;
下面来看请求
//call.enqueue
@Override 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)); }
由以上代码 可以看出来 okhttp的请求是由dispatcher来完成的;而dispatcher又是什么呢 ?
其实是一个网络的任务调度器;
那么下面来看下调度器的实现.
3.dispatcher任务调度
//最大请求数 private int maxRequests = 64; //最大主机请求数 private int maxRequestsPerHost = 5; private @Nullable Runnable idleCallback; //消费者线程池 private @Nullable ExecutorService executorService; //将要运行的异步请求队列 private final Deque<AsyncCall> readyAsyncCalls = new ArrayDeque<>(); //正在运行的异步请求队列 private final Deque<AsyncCall> runningAsyncCalls = new ArrayDeque<>(); //正在运行的同步请求队列 private final Deque<RealCall> runningSyncCalls = new ArrayDeque<>(); public Dispatcher(ExecutorService executorService) { this.executorService = executorService; } public Dispatcher() { }
Dispatcher主要用于控制并发 并且维护了一部分变量
在请求之前dispatcher会自己创建线程池
当然也可以有程序员自己来创建线程池
ok~初步了解调度器之后来看异步请求的源码
synchronized void enqueue(AsyncCall call) { if (runningAsyncCalls.size() < maxRequests && runningCallsForHost(call) < maxRequestsPerHost) { runningAsyncCalls.add(call); executorService().execute(call); } else { readyAsyncCalls.add(call); } }
在调度器的enqueue中会先判断当前最大请求数和当前最大主机请求数 如果不超过默认的最大值 则吧请求加入到正在运行的请求队列—->runningAsyncCalls;
否则会加入到将要运行的请求队列中进行等待—->readyAsyncCalls
然后 executorService().execute(call);开始运行传入的线程 即传入的AsyncCall;而AsyncCall作为RealCall的内部实现类 会走execute;
ok下面来看AsyncCall–>execute ,在这里 开始进行网络请求:
@Override protected void execute() { boolean signalledCallback = false; try { Response response = getResponseWithInterceptorChain(); if (retryAndFollowUpInterceptor.isCanceled()) { signalledCallback = true; responseCallback.onFailure(RealCall.this, new IOException("Canceled")); } else { signalledCallback = true; 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 { client.dispatcher().finished(this); } } }
在上面代码中不难看出走了一系列方法 来进行网络请求 为了方便读者理解 先来看finally下的方法 (这个方法必然会走到的):
void finished(AsyncCall call) { finished(runningAsyncCalls, call, true); } //finished private <T> void finished(Deque<T> calls, T call, boolean promoteCalls) { int runningCallsCount; Runnable idleCallback; synchronized (this) { if (!calls.remove(call)) throw new AssertionError("Call wasn't in-flight!"); if (promoteCalls) promoteCalls(); runningCallsCount = runningCallsCount(); idleCallback = this.idleCallback; } if (runningCallsCount == 0 && idleCallback != null) { idleCallback.run(); } } //####promoteCalls() private void promoteCalls() { if (runningAsyncCalls.size() >= maxRequests) return; // Already running max capacity. if (readyAsyncCalls.isEmpty()) return; // No ready calls to promote. for (Iterator<AsyncCall> i = readyAsyncCalls.iterator(); i.hasNext(); ) { AsyncCall call = i.next(); if (runningCallsForHost(call) < maxRequestsPerHost) { i.remove(); runningAsyncCalls.add(call); executorService().execute(call); } if (runningAsyncCalls.size() >= maxRequests) return; // Reached max capacity. } }
直接提取关键代码:
finished—->if (promoteCalls) promoteCalls(); 当请求完之后 promoteCalls为true 则会走promoteCalls() ;从上面代码中可图看出来promoteCalls()中用迭代器遍历readyAsyncCalls 然后加入到runningAsyncCalls
其实就是在请求完成后 来请求缓存池中的线程
那么继续回头看AsyncCall–>execute中的逻辑,在这之前先简单介绍一下拦截器 okhttp中请求有用到拦截器
4.拦截器Interceptors
拦截器主要是用来监听网络的请求和响应 拦截器的添加可以添加,移除或者转换请求头;其实简单来说就是对网络请求和响应的一个包装吧,有兴趣可以自己研究一下 这里简单介绍一下方便接下来的讲解;继续回到代码:AsyncCall–>execute:
@Override protected void execute() { boolean signalledCallback = false; try { Response response = getResponseWithInterceptorChain(); if (retryAndFollowUpInterceptor.isCanceled()) { signalledCallback = true; responseCallback.onFailure(RealCall.this, new IOException("Canceled")); } else { signalledCallback = true; 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 { client.dispatcher().finished(this); } }
上面代码中关键的请求代码是:
Response response = getResponseWithInterceptorChain();
下面我们来看见其源码:
Response getResponseWithInterceptorChain() throws IOException { // Build a full stack of interceptors. 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() c9e5 ); return chain.proceed(originalRequest); }
在上面代码中:
Interceptor.Chain chain = new RealInterceptorChain(interceptors, null, null, null, 0, originalRequest, this, eventListener, client.connectTimeoutMillis(), client.readTimeoutMillis(), client.writeTimeoutMillis());
其实是初始化了拦截器 传参为读取/请求超时等….
实际请求的代码是:chain.proceed(originalRequest);
@Override public Response proceed(Request request) throws IOException { // If there's another interceptor in the chain, call that. if (index < client.interceptors().size()) { Interceptor.Chain chain = new ApplicationInterceptorChain(index + 1, request, forWebSocket); //从拦截器列表取出拦截器 Interceptor interceptor = client.interceptors().get(index); Response interceptedResponse = interceptor.intercept(chain); if (interceptedResponse == null) { throw new NullPointerException("application interceptor " + interceptor + " returned null"); } return interceptedResponse; } // No more interceptors. Do HTTP. return getResponse(request, forWebSocket); }
在拦截器拦截过程中,当存在多个拦截器,需要拦截等待,即第一个请求完下一个请求;其中拦截的代码会在上面代码中:
Interceptor interceptor = client.interceptors().get(index); Response interceptedResponse = interceptor.intercept(chain);
而真正请求的代码是//getResponse(request, forWebSocket);
那么接着来看它的源码:
Response getResponse(Request request, boolean forWebSocket) throws IOException { //请求成功的核心源码 engine = new HttpEngine(client, request, false, false, forWebSocket, null, null, null); int followUpCount = 0; while (true) { if (canceled) { engine.releaseStreamAllocation(); throw new IOException("Canceled"); } boolean releaseConnection = true; try { engine.sendRequest(); engine.readResponse(); releaseConnection = false; } catch (RequestException e) { // The attempt to interpret the request failed. Give up. throw e.getCause(); } catch (RouteException e) { ... } //请求失败的核心源码 boolean releaseConnection = true; try { engine.sendRequest(); engine.readResponse(); releaseConnection = false; } catch (RequestException e) { // The attempt to interpret the request failed. Give up. throw e.getCause(); } catch (RouteException e) { // The attempt to connect via a route failed. The request will not have been sent. HttpEngine retryEngine = engine.recover(e.getLastConnectException(), null); if (retryEngine != null) { releaseConnection = false; engine = retryEngine; continue; } // Give up; recovery is not possible. throw e.getLastConnectException(); } catch (IOException e) { // An attempt to communicate with a server failed. The request may have been sent. HttpEngine retryEngine = engine.recover(e, null); if (retryEngine != null) { releaseConnection = false; engine = retryEngine; continue; } // Give up; recovery is not possible. throw e; } finally { // We're throwing an unchecked exception. Release any resources. if (releaseConnection) { StreamAllocation streamAllocation = engine.close(); streamAllocation.release(); } } ..... engine = new HttpEngine(client, request, false, false, forWebSocket, streamAllocation, null, response); } }
到这里okhttp3的源码就解析完毕了 感谢支持 希望可以帮到你们~
相关文章推荐
- Volley完全解析——使用、源码
- OkHttp完全解析(八)源码解析一
- OKHttp使用详解及源码解析
- OKHttp使用完全解析
- OKHttp使用详解及源码解析
- OkHttp完全解析(十)源码解析三
- Android 图片加载框架Picasso基本使用和源码完全解析
- Android网络请求框架----Okhttp3完全解析(1),使用篇
- OkHttp完全解析(九)源码解析二
- HandlerThread 使用及其源码完全解析
- OKHTTP 的使用完全解析
- okhttp 使用完全解析
- 深入Android HandlerThread 使用及其源码完全解析
- okhttp 使用完全解析
- HandlerThread 的使用及其源码完全解析
- Android事件分发机制完全解析,带你从源码的角度彻底理解(上)
- Android事件分发机制完全解析,带你从源码的角度彻底理解(下)
- Android事件分发机制完全解析,带你从源码的角度彻底理解(下)
- Android事件分发机制完全解析,带你从源码的角度彻底理解(上)
- Android事件分发机制完全解析,带你从源码的角度彻底理解(下)