基于 RESTful Api设计规范的 Http 网络请求框架的封装。网络请求本质上还是使用OkHttp完成,而Retrofit负责网络网络请求接口的封装。
1.创建Retrofit实例
使用 Builder模式 创建一个Retrofit实例
OkHttpClient.Builder builder = new OkHttpClient.Builder();
OkHttpClient httpClient = builder.build();
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://api.example.com/") // 设置网络请求的URL地址
.addConverterFactory(GsonConverterFactory.create()) // 设置数据解析器
.client(httpClient)
.build();
2.定义接口以及请求方法
public interface ApiServicie
{
@POST("/"+ RequestParams.VERSION+"/api/***")
Call getCall(@Body RequestBody body);
}
3.创建网络请求接口实例
private Map mServicePool = new ConcurrentHashMap<>();
/**
* 获取指定类型的service,把service做缓存处理,避免每次都创建;
* 创建并获取网络请求接口
* @param clazz 网络请求接口的字节码
* @param 得到被动态代理的接口实例
* @return
*/
public synchronized T getService(Class clazz) {
Object service = mServicePool.get(clazz.getName());
if (service == null) {
service = mRetrofit.create(clazz);
mServicePool.put(clazz.getName(), service);
}
return (T) service;
}
// 使用动态代理的方式去拦截网络请求接口定义的方法
public T create(final Class service) {
if (validateEagerly) {
eagerlyValidateMethods(service);
}
// 使用动态代理,返回Service对象。当调用service.xxx()时会执行invoke方法并返回网络请求的对象Call
return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class>[] { service },
new InvocationHandler() {
@Override public Object invoke(Object proxy, Method method, @Nullable Object[] args) throws Throwable {
ServiceMethod
4.执行网络请求
// 生成网络请求Call对象
// 执行getCall方法时,会被动态代理的InvocationHandler.invoke拦截
Call call = getService(ApiService.class).getCall(body);
// 执行异步网络请求
call.enqueue(new Callback() {
@Override
public void onResponse(Call call, Response response) {
if (response.code() == 200) {
// 处理请求成功
} else {
// 处理请求失败
}
}
@Override
public void onFailure(Call call, Throwable t) {
// 处理请求失败
}
});
final class ExecutorCallAdapterFactory extends CallAdapter.Factory {
static final class ExecutorCallbackCall implements Call {
final Executor callbackExecutor; // 实现将子线程线程切换到UI线程
final Call delegate; // 静态代理OkHttpCall
ExecutorCallbackCall(Executor callbackExecutor, Call delegate) {
this.callbackExecutor = callbackExecutor;
this.delegate = delegate;
}
@Override public void enqueue(final Callback callback) {
checkNotNull(callback, "callback == null");
delegate.enqueue(new Callback() {
@Override public void onResponse(Call call, final Response response) {
// 执行线程切换
callbackExecutor.execute(new Runnable() {
@Override public void run() {
if (delegate.isCanceled()) {
// Emulate OkHttp's behavior of throwing/delivering an IOException on cancellation.
callback.onFailure(ExecutorCallbackCall.this, new IOException("Canceled"));
} else {
callback.onResponse(ExecutorCallbackCall.this, response);
}
}
});
}
@Override public void onFailure(Call call, final Throwable t) {
callbackExecutor.execute(new Runnable() {
@Override public void run() {
callback.onFailure(ExecutorCallbackCall.this, t);
}
});
}
});
}
}
OkHttpCall:
@Override public void enqueue(final Callback callback) {
okhttp3.Call call
Throwable failure;
synchronized (this) {
if (executed) throw new IllegalStateException("Already executed.");
executed = true;
// 生成原生的请求对象,会把请求参数通过serviceMethod.toCall()交由ParameterHandler组成网络请求头
call = rawCall;
failure = creationFailure;
if (call == null && failure == null) {
try {
call = rawCall = createRawCall();
} catch (Throwable t) {
throwIfFatal(t);
failure = creationFailure = t;
}
}
}
if (failure != null) {
callback.onFailure(this, failure);
return;
}
if (canceled) {
call.cancel();
}
// 调用OkHttp的enqueue执行网络请求
call.enqueue(new okhttp3.Callback() {
@Override public void onResponse(okhttp3.Call call, okhttp3.Response rawResponse) {
// 将服务器传回来的数据进行解析,生成对应的接收类型。
Response response;
try {
response = parseResponse(rawResponse);
} catch (Throwable e) {
callFailure(e);
return;
}
try {
// 将结果通过回调传递出去
callback.onResponse(OkHttpCall.this, response);
} catch (Throwable t) {
t.printStackTrace();
}
}
@Override public void onFailure(okhttp3.Call call, IOException e) {
callFailure(e);
}
private void callFailure(Throwable e) {
try {
callback.onFailure(OkHttpCall.this, e);
} catch (Throwable t) {
t.printStackTrace();
}
}
});
}
private okhttp3.Call createRawCall() throws IOException {
// args :网络请求传递的参数
okhttp3.Call call = serviceMethod.toCall();
if (call == null) {
throw new NullPointerException("Call.Factory returned null.");
}
return call;
}
}
RealCall
public void enqueue(Callback responseCallback) {
client.dispatcher().enqueue(new AsyncCall(responseCallback));
}
Dispatcher
public final class Dispatcher {
private int maxRequests = 64; // 最多缓存 64 个请求
private int maxRequestsPerHost = 5; // 同一个host最多允许5个链接存活
private @Nullable ExecutorService executorService; // 使用线程池执行请求
// 请求连接池
private final Deque runningSyncCalls = new ArrayDeque<>();
private final Deque runningAsyncCalls = new ArrayDeque<>();
private final Deque readyAsyncCalls = new ArrayDeque<>();
// 核心线程数为0,最大线程数为无限大,线程最多存活时间为1分钟。
// 当执行第二个线程时,第一个请求已经完成且在存活时间内,则复用第一个线程。
public synchronized ExcutorService excutorService() {
if(executorService == null) {
executorService = new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60, TimeUnit.SECONDS,
new SynchronousQueue(), Util.threadFactory("OkHttp Dispatcher", false));
}
}
// 执行异步网络请求
synchronized void enqueue(AsyncCall call) {
if (runningAsyncCalls.size() < maxRequests && runningCallsForHost(call) < maxRequestsPerHost) {
runningAsyncCalls.add(call);
executorService().execute(call);
} else {
readyAsyncCalls.add(call);
}
}
// 同步网络请求
synchronized void executed(RealCall call) {
runningSyncCalls.add(call);
}
}
public class AsyncCall extends NameRunnable{
@Override protected void execute() {
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);
}
}
}
RealCall
Response getResponseWithInterceptorChain() throws IOException {
// Build a full stack of interceptors.
List interceptors = new ArrayList<>();
interceptors.addAll(client.interceptors()); //自定义的拦截器
interceptors.add(retryAndFollowUpInterceptor); //重试拦截器,请求失败后重试, 如果出现IO异常则直接取消
interceptors.add(new BridgeInterceptor(client.cookieJar())); //桥接拦截器,处理请求
interceptors.add(new CacheInterceptor(client.internalCache())); //缓存拦截器,处理请求缓存
interceptors.add(new ConnectInterceptor(client)); //连接拦截器,创建HTTP连接
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);
}
将一个请求的过程分解,然后对每一个过程进行处理(打包),得到响应后在对数据进行解包.
public Response intercept(Chain chain) throws IOException {
//......
int followUpCount = 0; // 重试计数器
//通过一个循环来重新尝试请求
while (true) {
// 如果出现IO异常,则直接取消
if (canceled) {
streamAllocation.release();
throw new IOException("Canceled");
}
Response response;
boolean releaseConnection = true;
try {
// 1.执行下一个拦截器
response = realChain.proceed(request, streamAllocation, null, null);
releaseConnection = false;
}
// 2.检测服务端的响应 response, 是否需要重定向和以及客户端是否支持超时重连, 如果不支持则直接返回响应。
Request followUp = followUpRequest(response, streamAllocation.route);
if (followUp == null) {
if (!forWebSocket) {
streamAllocation.release();
}
//3. 返回response,请求完成
return response;
}
if (++followUpCount > MAX_FOLLOW_UPS) { // 最多尝试20次
streamAllocation.release();
throw new ProtocolException("Too many follow-up requests: " + followUpCount);
}
//4.重新设置请求
request = followUp;
//.......
}
}
public Response intercept(Chain chain) throws IOException {
Request userRequest = chain.request();
Request.Builder requestBuilder = userRequest.newBuilder();
RequestBody body = userRequest.body();
// 处理请求体
if (body != null) {
// ......
}
if (userRequest.header("Host") == null) {
requestBuilder.header("Host", hostHeader(userRequest.url(), false));
}
// 默认支持长连接
if (userRequest.header("Connection") == null) {
requestBuilder.header("Connection", "Keep-Alive");
}
// 默认支持 gzip 压缩
boolean transparentGzip = false;
if (userRequest.header("Accept-Encoding") == null && userRequest.header("Range") == null) {
transparentGzip = true;
requestBuilder.header("Accept-Encoding", "gzip");
}
// 默认使用cookie在用户端保存信息
List cookies = cookieJar.loadForRequest(userRequest.url());
if (!cookies.isEmpty()) {
requestBuilder.header("Cookie", cookieHeader(cookies));
}
// 默认支持代理
if (userRequest.header("User-Agent") == null) {
requestBuilder.header("User-Agent", Version.userAgent());
}
// 执行请求
// .....
}
return responseBuilder.build();
}
总结:桥接连接器主要是优化请求头的一些配置,例如:默认支持长连接;默认支持 gzip 压缩。
该拦截器主要是处理HTTP响应缓存的,如果。
总结如下:
- 使用 DiskLruCache 管理Http的响应缓存;
- 使用 CacheControll 验证缓存是否可用。
首先,OkHttp 会将请求缓存在一个连接池(ConnectionPool : 最多有5个空闲链接,一个链接最多存活5分钟,使用核心线程数为0,最大线程数为1,每个线程最多存活1分钟的线程池)中;接着,收到请求时,根据请求地址从连接池中查找是否有链接,如果有则返回;否则创建一个新的链接返回并加入连接池;
该拦截器是整个请求的最后一步: 与服务端交换数据。
public Response intercept(Chain chain) throws IOException {
//......
//写入请求头数据
httpCodec.writeRequestHeaders(request);
realChain.eventListener().requestHeadersEnd(realChain.call(), request);
Response.Builder responseBuilder = null;
if (HttpMethod.permitsRequestBody(request.method()) && request.body() != null) {
//......
if (responseBuilder == null) {
// Write the request body if the "Expect: 100-continue" expectation was met.
realChain.eventListener().requestBodyStart(realChain.call());
long contentLength = request.body().contentLength();
//这里写入请求体
CountingSink requestBodyOut =
new CountingSink(httpCodec.createRequestBody(request, contentLength));
BufferedSink bufferedRequestBody = Okio.buffer(requestBodyOut);
request.body().writeTo(bufferedRequestBody);
bufferedRequestBody.close();
realChain.eventListener()
.requestBodyEnd(realChain.call(), requestBodyOut.successfulCount);
} else if (!connection.isMultiplexed()) {
streamAllocation.noNewStreams();
}
}
// 执行请求
httpCodec.finishRequest();
if (responseBuilder == null) {
//这里请求返回,读取响应请求头
realChain.eventListener().responseHeadersStart(realChain.call());
responseBuilder = httpCodec.readResponseHeaders(false);
}
// 根据响应创建 Response
Response response = responseBuilder
.request(request)
.handshake(streamAllocation.connection().handshake())
.sentRequestAtMillis(sentRequestMillis)
.receivedResponseAtMillis(System.currentTimeMillis())
.build();
realChain.eventListener()
.responseHeadersEnd(realChain.call(), response);
int code = response.code();
if (forWebSocket && code == 101) {
response = response.newBuilder()
.body(Util.EMPTY_RESPONSE)
.build();
} else {
//读取返回内容
response = response.newBuilder()
.body(httpCodec.openResponseBody(response))
.build();
}
//......
return response;
}