定制目的
我们的最终目的是将中间层拿掉,直接集成okhttp的包装框架,JLRetrofit的存在其实就是来兼容我们老的逻辑,让各端能平滑过渡,慢慢迁移。
博客内容
- 了解Retrofit背后的知识,深入理解
- 分析Mini版Retrofit框架代码
理解Retrofit
下面详细了解下四个知识点,懂了之后你就会发现,retrofit真的很简单。 最核心的四个知识点
- 注解
- 动态代理
- 反射
- 设计模式
注解
注解原理点我或者直接看下图
动态代理
原理请看点我
反射
原理请看点我
设计模式
整个流程中运用的设计模式如下 设计模式
分析Mini版Retrofit框架代码
我们分析的流程如下: 分析POST注解->如何解析出POST注解内容->根据解析的数据发送POST请求
POST注解
@Documented //注释放到javaDoc中 @Target(METHOD) //注释目标是方法 @Retention(RUNTIME) // 运行时保留 public @interface POST { /** * A relative or absolute path, or full URL of the endpoint. This value is optional if the first * <p> * this is resolved against a base URL to create the full endpoint URL. */ String value() default "";
如何解析出POST注解内容
通过搜索查到这,这里判断了注解Annotation 是否是POST类型,是就解析POST类型需要的其他字段
private void parseMethodAnnotation(Annotation annotation) { if (annotation instanceof POST) { this.parseHttpMethodAndPath("POST", ((POST) annotation).value(), true); } }
往上层继续找,RequestFactory build函数里,对一个变量methodAnnotions遍历解析,再找一下this.methodAnnotations哪里来的
RequestFactory build() { Annotation[] var1 = this.methodAnnotations; int p = var1.length; int lastParameter; for (lastParameter = 0; lastParameter < p; ++lastParameter) { Annotation annotation = var1[lastParameter]; this.parseMethodAnnotation(annotation); }
同样还在RequestFactory类中,通过Method类method.getAnnotations()获取的。
Builder(JLRetrofit retrofit, Method method) { this.retrofit = retrofit; this.method = method; this.methodAnnotations = method.getAnnotations(); this.parameterTypes = method.getGenericParameterTypes(); this.parameterAnnotationsArray = method.getParameterAnnotations(); }
继续往上找,静态函数,parseAnnotations传递过来。
static RequestFactory parseAnnotations(JLRetrofit retrofit, Method method) { return (new RequestFactory.Builder(retrofit, method)).build(); }
继续,ServiceMethod抽象类,parseAnnotations函数中调用
static <T> ServiceMethod<T> parseAnnotations(JLRetrofit retrofit, Method method) { RequestFactory requestFactory = RequestFactory.parseAnnotations(retrofit, method); Type returnType = method.getGenericReturnType(); if (hasUnresolvableType(returnType)) { throw methodError(method, "Method return type must not include a type variable or wildcard: %s", returnType); } if (returnType == void.class) { throw methodError(method, "Service methods cannot return void."); } return HttpServiceMethod.parseAnnotations(retrofit, method, requestFactory); }
继续,在Retrofit类中 函数loadServiceMethod中调用。
private ServiceMethod<?> loadServiceMethod(Method method) { ServiceMethod<?> result = serviceMethodCache.get(method); if (result != null) return result; synchronized (serviceMethodCache) { result = serviceMethodCache.get(method); if (result == null) { result = ServiceMethod.parseAnnotations(this, method); serviceMethodCache.put(method, result); } } return result; } public <T> T create(final Class<T> service) { Utils.validateServiceInterface(service); return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class<?>[]{service}, new InvocationHandler() { private final Object[] emptyArgs = new Object[0]; @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { if (method.getDeclaringClass() == Object.class) { return method.invoke(this, args); } return loadServiceMethod(method).invoke(args != null ? args : emptyArgs); } }); }
最终看到了create函数,这个函数就是我们在创建api的过程中经常用到的函数。
Call<String> call = new JLRetrofit.Builder().baseUrl("http://").build().create(ServiceApi.class).getBaidu(); try { call.execute(); } catch (IOException e) { e.printStackTrace(); }
根据解析的数据发送POST请求
一个网络最终调用execute接口发送请求的,肯定有实现类,要不然如何请求的呢。option+command+B 看图
这里发现两个,最终发送网络请求的其实是OkhttpCall,这里实现了Okhttp的调用。看图,call是okhttp3包下的类
为什么有两个呢?这里用到一个设计模式,装饰者模式,跟我们RecylerView 的adapter一个概念,我们可以添加更多的Adapter来处理数据。 看类名ExecutorCallbackCall可以猜到,这是一个线程管理装饰者,负责异步处理的。 网络请求的参数哪里来的呢,其实所有的参数和注解的内容已经解析出来存在RequestFactory中。
OkHttpCall(RequestFactory requestFactory, Object[] args) { this.requestFactory = requestFactory; this.args = args; }
如图:url、body、httpMethod都会在这个类里解析出来。
整个流程分析完了,准备的比较仓促,不全面,抱歉啊,接下来直接看源码吧。
总结
一个Retrofit框架,整体设计结构蕴藏着很多设计模式,很多良好的代码书写习惯。多分析,多看看,还是有很多收获的。分享就到这,有问题请留言。