基于 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<ResponseBody> getCall(@Body RequestBody body); }3.创建网络请求接口实例
private Map<String, Object> mServicePool = new ConcurrentHashMap<>(); /** * 获取指定类型的service,把service做缓存处理,避免每次都创建; * 创建并获取网络请求接口 * @param clazz 网络请求接口的字节码 * @param <T> 得到被动态代理的接口实例 * @return */ public synchronized <T> T getService(Class<T> clazz) { Object service = mServicePool.get(clazz.getName()); if (service == null) { service = mRetrofit.create(clazz); mServicePool.put(clazz.getName(), service); } return (T) service; } // 使用动态代理的方式去拦截网络请求接口定义的方法 public <T> T create(final Class<T> 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<Object, Object> serviceMethod = (ServiceMethod<Object, Object>) loadServiceMethod(method); OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args); return serviceMethod.adapt(okHttpCall); } }); } // 根据缓存策略实现延伸加载ServiceMethod对象 ServiceMethod<?, ?> loadServiceMethod(Method method) { ServiceMethod<?, ?> result = serviceMethodCache.get(method); if (result != null) return result; synchronized (serviceMethodCache) { result = serviceMethodCache.get(method); if (result == null) { result = new ServiceMethod.Builder<>(this, method).build(); serviceMethodCache.put(method, result); } } return result; } Builder(Retrofit retrofit, Method method) { this.retrofit = retrofit; this.method = method; this.methodAnnotations = method.getAnnotations(); // 获取方法注解 this.parameterTypes = method.getGenericParameterTypes(); // 获取参数类型 this.parameterAnnotationsArray = method.getParameterAnnotations();//获取参数注解 } public ServiceMethod build() { callAdapter = createCallAdapter(); // 获取网络请求适配器,默认使用带线程切换的适配器 responseType = callAdapter.responseType(); // 获取响应类型 if (responseType == Response.class || responseType == okhttp3.Response.class) { throw methodError("'" + Utils.getRawType(responseType).getName() + "' is not a valid response body type. Did you mean ResponseBody?"); } responseConverter = createResponseConverter(); // 获取服务器数据解析器 // 解析方法注解 for (Annotation annotation : methodAnnotations) { parseMethodAnnotation(annotation); } int parameterCount = parameterAnnotationsArray.length; parameterHandlers = new ParameterHandler<?>[parameterCount]; for (int p = 0; p < parameterCount; p++) { Type parameterType = parameterTypes[p]; if (Utils.hasUnresolvableType(parameterType)) { throw parameterError(p, "Parameter type must not include a type variable or wildcard: %s", parameterType); } Annotation[] parameterAnnotations = parameterAnnotationsArray[p]; if (parameterAnnotations == null) { throw parameterError(p, "No Retrofit annotation found."); } // 将参数注解以及参数类型生成参数转换器 parameterHandlers[p] = parseParameter(p, parameterType, parameterAnnotations); } return new ServiceMethod<>(this); }4.执行网络请求
// 生成网络请求Call对象 // 执行getCall方法时,会被动态代理的InvocationHandler.invoke拦截 Call<ResponseBody> call = getService(ApiService.class).getCall(body); // 执行异步网络请求 call.enqueue(new Callback<ResponseBody>() { @Override public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) { if (response.code() == 200) { // 处理请求成功 } else { // 处理请求失败 } } @Override public void onFailure(Call<ResponseBody> call, Throwable t) { // 处理请求失败 } }); final class ExecutorCallAdapterFactory extends CallAdapter.Factory { static final class ExecutorCallbackCall<T> implements Call<T> { final Executor callbackExecutor; // 实现将子线程线程切换到UI线程 final Call<T> delegate; // 静态代理OkHttpCall ExecutorCallbackCall(Executor callbackExecutor, Call<T> delegate) { this.callbackExecutor = callbackExecutor; this.delegate = delegate; } @Override public void enqueue(final Callback<T> callback) { checkNotNull(callback, "callback == null"); delegate.enqueue(new Callback<T>() { @Override public void onResponse(Call<T> call, final Response<T> 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<T> call, final Throwable t) { callbackExecutor.execute(new Runnable() { @Override public void run() { callback.onFailure(ExecutorCallbackCall.this, t); } }); } }); } } OkHttpCall: @Override public void enqueue(final Callback<T> 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<T> 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<RealCall> runningSyncCalls = new ArrayDeque<>(); private final Deque<AsyncCall> runningAsyncCalls = new ArrayDeque<>(); private final Deque<AsyncCall> readyAsyncCalls = new ArrayDeque<>(); // 核心线程数为0,最大线程数为无限大,线程最多存活时间为1分钟。 // 当执行第二个线程时,第一个请求已经完成且在存活时间内,则复用第一个线程。 public synchronized ExcutorService excutorService() { if(executorService == null) { executorService = new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60, TimeUnit.SECONDS, new SynchronousQueue<Runnable>(), 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<Interceptor> 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); }将一个请求的过程分解,然后对每一个过程进行处理(打包),得到响应后在对数据进行解包.
重试拦截器 - RetryAndFollowUpInterceptor 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; //....... } } 桥接拦截器 - BridgeInterceptor 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<Cookie> 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 压缩。
请求缓存拦截器 - CacheInterceptor该拦截器主要是处理HTTP响应缓存的,如果。
总结如下:
使用 DiskLruCache 管理Http的响应缓存;使用 CacheControll 验证缓存是否可用。 连接拦截器 - ConnectInterceptor首先,OkHttp 会将请求缓存在一个连接池(ConnectionPool : 最多有5个空闲链接,一个链接最多存活5分钟,使用核心线程数为0,最大线程数为1,每个线程最多存活1分钟的线程池)中;接着,收到请求时,根据请求地址从连接池中查找是否有链接,如果有则返回;否则创建一个新的链接返回并加入连接池;
CallServerInterceptor该拦截器是整个请求的最后一步: 与服务端交换数据。
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; }