张士超 2018-08-29 1362浏览量
OkHttp是一个非常优秀的网络请求框架,已被谷歌加入到Android的源码中。目前比较流行的Retrofit也是默认使用OkHttp的。所以OkHttp的源码是一个不容错过的学习资源,学习源码之前,务必熟练使用这个框架,否则就是跟自己过不去。
至于为什么有这么多优点,各位看官老爷在下面的源码解析中慢慢体会吧!
既然是网络框架,那么先来看看它的post和get请求吧。总的来说,分为三步:
OkHttpClient okHttpClient = new OkHttpClient();
Request request = new Request.Builder().url(URL).build();
okHttpClient.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
}
@Override
public void onResponse(Call call, Response response) throws IOException {
String dataStr=response.body().string();
Log.e("info",dataStr);
}
});
OkHttpClient okHttpClient = new OkHttpClient();
Response response = okHttpClient.newCall(request).execute();
String dataStr=response.body().string();
OkHttpClient okHttpClient = new OkHttpClient();
RequestBody requestBody = new FormBody
.Builder()
.add("name", "张士超")
.add("password", "123456")
.build();
Request request = new Request
.Builder()
.url(URL)
.post(requestBody)
.build();
okHttpClient.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
}
@Override
public void onResponse(Call call, Response response) throws IOException {
String dataStr=response.body().string();
Log.e("info",dataStr);
}
});
OkHttpClient okHttpClient = new OkHttpClient();
RequestBody requestBody = new FormBody
.Builder()
.add("name", "张士超")
.add("password", "123456")
.build();
Request request = new Request
.Builder()
.url(URL)
.post(requestBody)
.build();
try {
Response response = okHttpClient.newCall(request).execute();
String dataStr=response.body().string();
} catch (IOException e) {
e.printStackTrace();
}
首先我们看看okhttp源码涉及到的几个类的源码:
public final class Request {
final HttpUrl url;
final String method;
final Headers headers;
final @Nullable RequestBody body;
final Object tag;
private volatile CacheControl cacheControl; // Lazily initialized.
这里面比较重要的是url、method、header和RequestBody,分别代表request请求的请求URL、请求方法、请求头和请求体。
public final class Response implements Closeable {
final Request request;
final Protocol protocol;
final int code;
final String message;
final @Nullable Handshake handshake;
final Headers headers;
final @Nullable ResponseBody body;
final @Nullable Response networkResponse;
final @Nullable Response cacheResponse;
final @Nullable Response priorResponse;
final long sentRequestAtMillis;
final long receivedResponseAtMillis;
这里面比较重要的是code响应码、message响应信息、headers响应头和body响应体。
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;
final @Nullable Cache cache;
final @Nullable InternalCache internalCache;
final SocketFactory socketFactory;
final @Nullable SSLSocketFactory sslSocketFactory;
final @Nullable CertificateChainCleaner certificateChainCleaner;
final HostnameVerifier hostnameVerifier;
final CertificatePinner certificatePinner;
final Authenticator proxyAuthenticator;
final Authenticator authenticator;
final ConnectionPool connectionPool;
final Dns dns;
final boolean followSslRedirects;
final boolean followRedirects;
final boolean retryOnConnectionFailure;
final int connectTimeout;
final int readTimeout;
final int writeTimeout;
final int pingInterval;
Okhttp包含的东西很多,这里我们需要重点关注的是dispatcher调度器,interceptors自定义应用拦截器和networkInterceptors自定义网络拦截器。
ok,比较重要的三个类介绍完了,接下来我们看一看同步和异步请求的源码解析,先放一张图(盗的别人的图hhhh),让看官老爷门大致上有一个印象,后面比较好理解。
整个过程大致说一下吧,首先不管啥请求okHttpClient.newCall(request)这玩意实际上返回一个RealCall类,然后同步请求调用execute(),异步调用enqueue()之后给调度器,其实同步和异步都给了调度器,只是异步调用了调度器的execute()进行请求调度处理,下面给一张图就了解啦:
以下面代码为例,看看源码都干了啥:
OkHttpClient okHttpClient = new OkHttpClient();
Request request = new Request.Builder().url(URL).build();
okHttpClient.newCall(request).enqueue(new Callback()/execute()
前面两句话就不说了,就是OkHttpClient和Request 对象的实例化,我们看看okHttpClient.newCall(request)这里都干了些啥:
@Override public Call newCall(Request request) {
return RealCall.newRealCall(this, request, false );
}
进去newRealCall,看看:
static RealCall newRealCall(OkHttpClient client, Request originalRequest, boolean forWebSocket) {
RealCall call = new RealCall(client, originalRequest, forWebSocket);
call.eventListener = client.eventListenerFactory().create(call);
return call;
}
总之就是工厂模式将request封装成一个RealCall对象,接着看okHttpClient.newCall(request).execute(),同步请求;
@Override public Response execute() throws IOException {
synchronized (this) {//1
if (executed) throw new IllegalStateException("Already Executed");
executed = true;
}
captureCallStackTrace();
eventListener.callStart(this);
try {
client.dispatcher().executed(this);//2
Response result = getResponseWithInterceptorChain();//3
if (result == null) throw new IOException("Canceled");
return result;
} catch (IOException e) {
eventListener.callFailed(this, e);
throw e;
} finally {
client.dispatcher().finished(this);//3
}
}
比较重要的是上面三处注释:
synchronized void executed(RealCall call) {
runningSyncCalls.add(call);
}
将这个请求加入到runningSyncCalls队列中,后面详细说说这个调度器。
void finished(RealCall call) {
finished(runningSyncCalls, call, false);
}
将请求任务从runningSyncCalls队列中移除。
这样整个同步请求流程就实现了,看下面这个图会清晰很多:
public final class 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 synchronized ExecutorService executorService() {
if (executorService == null) {
executorService = new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>(), Util.threadFactory("OkHttp Dispatcher", false));
}
return executorService;
}
异步请求以下面这个为例,看看源码都怎么做的:
OkHttpClient okHttpClient = new OkHttpClient();
Request request = new Request.Builder().url(URL).build();
okHttpClient.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
}
@Override
public void onResponse(Call call, Response response) throws IOException {
String dataStr=response.body().string();
Log.e("info",dataStr);
}
});
@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));
}
synchronized void enqueue(AsyncCall call) {
if (runningAsyncCalls.size() < maxRequests && runningCallsForHost(call) < maxRequestsPerHost) {
runningAsyncCalls.add(call);
executorService().execute(call);
} else {
readyAsyncCalls.add(call);
}
}
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);
return chain.proceed(originalRequest);
}
1)在配置 OkHttpClient 时设置的 interceptors;
2)负责失败重试以及重定向的 RetryAndFollowUpInterceptor;
3)负责把用户构造的请求转换为发送到服务器的请求、把服务器返回的响应转换为用户友好的响应的 BridgeInterceptor;
4)负责读取缓存直接返回、更新缓存的 CacheInterceptor;
5)负责和服务器建立连接的 ConnectInterceptor;
6)配置 OkHttpClient 时设置的 networkInterceptors;
7)负责向服务器发送请求数据、从服务器读取响应数据的 CallServerInterceptor。
OkHttp的这种拦截器链采用的是责任链模式,这样的好处是将请求的发送和处理分开,并且可以动态添加中间的处理方实现对请求的处理、短路等操作。给个图加强理解:
版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。
集结各类场景实战经验,助你开发运维畅行无忧