一、简介
OKHttp是一个网络请求的开源项目,由移动支付Square公司贡献,用于替代HttpUrlConnection和Apache HttpClient(android API23 6.0里已移除HttpClient)
其主要优点有:
- 支持HTTP2/SPDY(共享同一个Socket来处理同一个服务器的所有请求)
- Socket自动选择最好路线,并支持自动重连,拥有自动维护的Socket连接池,减少握手次数,减少了请求延迟,共享Socket,减少对服务器的请求次数。
- 基于Headers的缓存策略减少重复的网络请求。
- 拥有Interceptors轻松处理请求与响应(自动处理GZip压缩)
二、基本用法
get的同步请求
OkHttpClient client = new OkHttpClient();//创建OkHttpClient对象
Request request = new Request.Builder().url("http://www.baidu.com").build();
//创建Request 对象
Response response = null;
response = client.newCall(request).execute();//得到Response 对象
if (response.isSuccessful()) {
Log.d("kwwl","response.code()=="+response.code());
Log.d("kwwl","response.message()=="+response.message());
Log.d("kwwl","res=="+response.body().string());
//此时的代码执行在子线程,修改UI的操作请使用handler跳转到UI线程。
}
get的异步请求
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder().url("http://www.baidu.com").build();
client.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
}
@Override
public void onResponse(Call call, Response response) throws IOException {
if(response.isSuccessful()){//回调的方法执行在子线程。
Log.d("kwwl","获取数据成功了");
Log.d("kwwl","response.code()=="+response.code());
Log.d("kwwl","response.body().string()=="+response.body().string());
}
}
});
post 请求
OkHttpClient client = new OkHttpClient();
String post(String url, String json) throws IOException {
RequestBody formBody = new FormEncodingBuilder()
.add("platform", "android")
.add("name", "bug")
.add("subject", "XXXXXXXXXXXXXXX")
.build();
Request request = new Request.Builder().url(url).post(body).build();
Response response = client.newCall(request).execute();
if (response.isSuccessful()) {
return response.body().string();
} else {
throw new IOException("Unexpected code " + response);
}
}
三、源码解析
下面是关于OKHttp的请求流程图:
- 同步请求
同步请求调用的是 execute 方法,在内部会调用 client.dispatcher().executed(this); 方法,进去看源码可知道它实际就是将 RealCall 添加到 Dispatcher 的 runningSyncCalls 中,表示当前正在执行的同步队列中。在这里使用 Dispacther 的中 execute 仅仅只是将其添加到集合中而已,没有作别的操作,而真正执行同步任务的核心代码是 getResponseWithInterceptorChain();
public Call newCall(Request request) {
return RealCall.newRealCall(this, request, false /* for web socket */);
}
// 同步请求方法
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);
}
}
// Dispatcher类里面的方法
synchronized void executed(RealCall call) {
runningSyncCalls.add(call);
}
- 异步请求
// 异步请求方法
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));
}
// Dispatcher类里面的方法
synchronized void enqueue(AsyncCall call) {
//当正在执行的请求小于64个&&该 call 对应的主机少于5个 Call 时
//将任务添加到 runningAsycnCalls 中,标记为正在执行的任务。
if (runningAsyncCalls.size() < maxRequests
&& runningCallsForHost(call) < maxRequestsPerHost) {
runningAsyncCalls.add(call);
//在线程池中执行这个任务。
executorService().execute(call);
} else {
readyAsyncCalls.add(call);
}
}
// 实现了Runnable 接口的线程
final class AsyncCall extends NamedRunnable {
....
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 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());
return chain.proceed(originalRequest);
}