什么是Retrofit
- retrofit 是Square公司为了方便网络请求,对自己okhttp底层网络请求进行了再一次封装的框架,意在简化网络请求调用。当然retrofit设计也并不单纯只为了okhttp服务,只是默认实现使用了okhttp。
Retrofit的实现
先来看retrofit的几个重要类
Retrofit
Retrofit adapts a Java interface to HTTP calls by using annotations on the declared methods to define how requests are made. Create instances using {@linkplain Builder the builder} and pass your interface to {@link #create} to generate an implementation.
- 通过动态代理的方式,解析方法申明上的注解来生成http请求。
- Retrofit实例主要充当一个适配器的角色。
Call
An invocation of a Retrofit method that sends a request to a webserver and returns a response. Each call yields its own HTTP request and response pair. Use {@link #clone} to make multiple calls with the same parameters to the same webserver; this may be used to implement polling or to retry a failed call.
- Retrofit方法的一个实现,向服务器发送一个请求,并返回一个响应
- 保存了一对http的请求以及响应
Converter<F, T>
Convert objects to and from their representation in HTTP. Instances are created by {@linkplain Factory a factory} which is {@linkplain Retrofit.Builder#addConverterFactory(Factory) installed} into the {@link Retrofit} instance.
- 对http响应进行转换,转换成请求接口需要的返回类型
CallAdapter<R, T>
Adapts a {@link Call} with response type {@code R} into the type of {@code T}. Instances are created by {@linkplain Factory a factory} which is {@linkplain Retrofit.Builder#addCallAdapterFactory(Factory) installed} into the {@link Retrofit} instance.
- 对请求进行适配,以满足接口要求
ServiceMethod<R, T>
Adapts an invocation of an interface method into an HTTP call.
- 将定义的网络请求方法适配成一个http call
ParameterHandler
- ServiceMethod解析参数时具体值保存的位置
RequestBuilder
- 构建一个初始的Request
Retrofit发起请求的过程
-
先看一下调用的代码。
Retrofit创建时使用的动态代理方式,中间的Platform就是根据不同的平台做了兼容。这里可以很清晰看到,对service进行代理,通过其中的method构建一个serviceMethod,进而new出okHttpCall,并使用serviceMethod内部持有的callAdapter对okHttpCall进行网路请求以及适配成用户期望的返回类型,完成一次网络请求。
public <T> T create(final Class<T> service) { Utils.validateServiceInterface(service); if (validateEagerly) { eagerlyValidateMethods(service); } return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class<?>[] { service }, new InvocationHandler() { private final Platform platform = Platform.get(); @Override public Object invoke(Object proxy, Method method, @Nullable Object[] args) throws Throwable { // If the method is a method from Object then defer to normal invocation. if (method.getDeclaringClass() == Object.class) { return method.invoke(this, args); } if (platform.isDefaultMethod(method)) { return platform.invokeDefaultMethod(method, service, proxy, args); } ServiceMethod<Object, Object> serviceMethod = (ServiceMethod<Object, Object>) loadServiceMethod(method); OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args); return serviceMethod.callAdapter.adapt(okHttpCall); } }); } -
ServiceMethod的构建
ServiceMethodg构建过程主要是对Service中定义的网络请求进行注解的解析处理,将完成的参数保存在ParameterHandler中以便后续取用,至于注解参数的获取比较琐碎,这里不做赘述。
-
CallAdapter的获取
private CallAdapter<T, R> createCallAdapter() { Type returnType = method.getGenericReturnType(); if (Utils.hasUnresolvableType(returnType)) { throw methodError( "Method return type must not include a type variable or wildcard: %s", returnType); } if (returnType == void.class) { throw methodError("Service methods cannot return void."); } Annotation[] annotations = method.getAnnotations(); try { //noinspection unchecked return (CallAdapter<T, R>) retrofit.callAdapter(returnType, annotations); } catch (RuntimeException e) { // Wide exception range because factories are user code. throw methodError(e, "Unable to create call adapter for %s", returnType); } }这里开始用到了工厂模式,使用CallAdapter.Factory的方式来获取CallAdapter。我们知道在构建Retrofit时是可以addCallAdapterFactory的,这就意味着我们可以自己实现CallAdapter,提供给Retrofit使用,提高代码的扩展性。
通过遍历Retrofit中保存的CallAdapter.Factory列表获取到符合条件的Factory用做请求的转换。
通过上面代码可以知道,实际上获取到的时候是retrofit中默认初始化的CallAdapter
-
默认CallAdapter
在Retrofit build过程中可以看到如下代码
Executor callbackExecutor = this.callbackExecutor; if (callbackExecutor == null) { callbackExecutor = platform.defaultCallbackExecutor(); } // Make a defensive copy of the adapters and add the default Call adapter. List<CallAdapter.Factory> adapterFactories = new ArrayList<>(this.adapterFactories); adapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor));通过平台的适配我们获取到的platform其实是如下Android平台
static class Android extends Platform { @Override public Executor defaultCallbackExecutor() { return new MainThreadExecutor(); } @Override CallAdapter.Factory defaultCallAdapterFactory(@Nullable Executor callbackExecutor) { if (callbackExecutor == null) throw new AssertionError(); return new ExecutorCallAdapterFactory(callbackExecutor); } static class MainThreadExecutor implements Executor { private final Handler handler = new Handler(Looper.getMainLooper()); @Override public void execute(Runnable r) { handler.post(r); } } }通过安卓平台可以初始化一个默认的ExecutorCallAdapterFactory,用以获取默认的CallAdapter。
通过ExecutorCallAdapterFactory可以get到一个CallAdapter的实现,并将Call适配成一个ExecutorCallbackCall,内部处理了网络请求以及线程的切换。
-
请求的梳理
通过上面的分析知道,默认的请求过程如下:
- 对Service进行动态代理
- 构建出ServiceMethod
- 通过ServiceMethod构建出OkHttpCall
- 通过ServiceMethod中的CallAdapter实际也就是ExecutorCallAdapterFactory,对OkHttpCall进行适配获取到我们所需要的Call对象
- 得到用户需要的Call之后就可以进行execute或者enqueue操作。
到这里基本的网络请求算是完了。
·~~~~~~~~~~~~~~~~~~·
·~~~~~~~~~~~~~~~~~~·
·~~~~~~我是分割线~~~~~~~·
·~~~~~~~~~~~~~~~~~~·
·~~~~~~~~~~~~~~~~~~·
等等!是不是感觉漏掉了什么东西,前面提到的Converter好像用到。
开头说过Converter是对响应做了转换,那肯定是在Call中用到,那我们回过头去看OkHttpCall的构建。
-
OkHttpCall
主要看一下response的解析
Response<T> parseResponse(okhttp3.Response rawResponse) throws IOException { ResponseBody rawBody = rawResponse.body(); // Remove the body's source (the only stateful object) so we can pass the response along. rawResponse = rawResponse.newBuilder() .body(new NoContentResponseBody(rawBody.contentType(), rawBody.contentLength())) .build(); int code = rawResponse.code(); if (code < 200 || code >= 300) { try { // Buffer the entire body to avoid future I/O. ResponseBody bufferedBody = Utils.buffer(rawBody); return Response.error(bufferedBody, rawResponse); } finally { rawBody.close(); } } if (code == 204 || code == 205) { rawBody.close(); return Response.success(null, rawResponse); } ExceptionCatchingRequestBody catchingBody = new ExceptionCatchingRequestBody(rawBody); try { T body = serviceMethod.toResponse(catchingBody); return Response.success(body, rawResponse); } catch (RuntimeException e) { // If the underlying source threw an exception, propagate that rather than indicating it was // a runtime exception. catchingBody.throwIfCaught(); throw e; } }我们来看这一句
T body = serviceMethod.toResponse(catchingBody);往上追溯到头可以知道,实际代码如下
public <T> Converter<ResponseBody, T> nextResponseBodyConverter( @Nullable Converter.Factory skipPast, Type type, Annotation[] annotations) { checkNotNull(type, "type == null"); checkNotNull(annotations, "annotations == null"); int start = converterFactories.indexOf(skipPast) + 1; for (int i = start, count = converterFactories.size(); i < count; i++) { Converter<ResponseBody, ?> converter = converterFactories.get(i).responseBodyConverter(type, annotations, this); if (converter != null) { //noinspection unchecked return (Converter<ResponseBody, T>) converter; } }也就是我们常设置的GsonConverterFactory会在这里被取用,并对真正的response做解析。
至此一个完整的网络请求以及参数的解析都完整结束了
总结
- Retrofit本身就是个适配器,用以协调资源
- 动态代码模式,每个请求都是动态生成
- 静态代理模式,如返回给我们的ExecutorCallbackCall,实际是对内部Call一个代理对象
- builder模式,简化对象的构建
- 使用了工厂模式,同时提高了代码的定制性
- 适配器模式,将原始的响应适配成实际需要的类型