OkHttp库使用及源码解析
特点
- OkHttp是一个高效的Http客户端,有如下的特点:
- 支持HTTP2/SPDY黑科技
- socket自动选择最好路线,并支持自动重连
- 拥有自动维护的socket连接池,减少握手次数
- 拥有队列线程池,轻松写并发
- 拥有Interceptors轻松处理请求与响应(比如透明GZIP压缩,LOGGING)
- 基于Headers的缓存策略
使用
OkHttp是由Square开发的网络通信库,使用前先添加依赖库
dependencies {
...
compile 'com.squareup.okhttp3:okhttp:3.4.1'
}
不要忘记声明使用网络的权限
<uses-permission android:name="android.permission.INTERNET" />
一个简单的GET请求的步骤(阻塞方式):
- 创建一个OkHttpClient对象
- 创建一个Request对象
- 调用client.newCall(request)创建Call对象
- 调用call.execute()执行请求(阻塞)
try
{
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder() //这里创建了Builder对象,然后进行配置
.url("http://www.baidu.com")
.build(); //创建Request对象
Response response = client.newCall(request).execute(); //创建一个Call对象,然后发送请求,response接收返回的数据,此方法blocks直到响应返回
String message = response.message(); //response状态
String responseData = response.body().string(); //将返回的数据转换为字符串
Log.d(TAG, "message : " + message);
Log.d(TAG, "data: \n" + responseData);
}
catch (Exception e)
{
e.printStackTrace();
}
当请求的域名不存在时会抛出异常:java.net.UnknownHostException
更好的用法(异步)
//创建okHttpClient对象
OkHttpClient mOkHttpClient = new OkHttpClient();
//创建一个Request
final Request request = new Request.Builder()
.url("https://github.com/hongyangAndroid")
.build();
//new call
Call call = mOkHttpClient.newCall(request);
//请求加入调度
call.enqueue(new Callback()
{
@Override
public void onFailure(Request request, IOException e)
{
//这里处理请求时发生的异常
}
@Override
public void onResponse(final Response response) throws IOException
{
//这里处理返回的response
}
});
调用enqueue()方法使得call的执行是异步的,不影响其他代码的执行。
当请求执行完后,会回调Callback里的方法,我们可以在里面执行我们的代码。
查看源码可以知道onFailure调用的时机:
Called when the request could not be executed due to cancellation, a connectivity problem or timeout.
当request由于取消、连接问题或者超时导致不能完成的情况下调用。
提交数据的POST请求
代码如下,其它跟上面的一样
RequestBody requestBody = new FormBody.Builder()
.add("username", "admin")
.add("password", "123456")
.build();
Request request = new Request.Builder() //这里创建了Builder对象,然后进行配置
.url("http://www.baidu.com")
.post(requestBody)
.build(); //创建Request对象
Builder的post()方法
public Builder post(RequestBody body) {
return method("POST", body);
}
当Builder调用了post(RequestBody)方法后自动将请求方法设为“POST”
源码解析
OkHttp中主要的几个类:
- RealCall,Call的实现类,读源码从这里入手
- RealConnection,Connection的实现类,主要做TCP连接和协议(TSL握手)处理
- HttpCodec,编码Http请求和解码Http响应
- OkHttpClient,做配置工作
- Dispatcher,做异步工作的分发
- RealInterceptorChain,拦截链,负责取出拦截器并执行
OkHttp的线程池
//最大同时请求数
private int maxRequests = 64;
//每个IP最多请求数
private int maxRequestsPerHost = 5;
synchronized void enqueue(AsyncCall call) {
//从判断条件可以看出,OKHttp3同时最多有64个请求执行,而每一个host最多有5个请求同时执行。其他请求都放在等待队列中。
if (runningAsyncCalls.size() < maxRequests && runningCallsForHost(call) < maxRequestsPerHost) {
runningAsyncCalls.add(call)