充足的时间才是第一辈子产力。当源码看多了以后,对于不少点的梳理上可能就不会像以前那样更具体了,本篇主要仍是在于对实现主流程的分析。Retrofit在以前项目中并无用到过,此次决定来看一些Retrofit相关实现来了解其中的原理。对于想要了解Java中的动态代理应用,想要用更简洁的方式实现网络请求,Retrofit多是最好的学习案例了,以前的项目中在写网络请求的时候,每次都须要写大量的样板代码来构造出一个网络请求,代码一旦增长,犯错误的几率也就会增长,维护成本也就增长,同时也下降了开发效率,工程化最佳实践的目标是让开发者只专一于本身的业务逻辑,而不须要关心下层具体的实现,尽量暴露少的业务无关的内容给到上层。git
对于Retrofit须要定义一个接口类,声明要请求的接口和其中参数的传递方式,而后经过调用create方法就能够构造一个Service类,调用相应的方法便可帮助咱们进行网络请求的发送,代码很是简洁,同时咱们也能够经过对不一样的业务模块分Service的方式来实现对于不一样业务接口的隔离。github
public interface GitHubService { @GET("users/{user}/repos") Call<List<Repo>> listRepos(@Path("user") String user); } Retrofit retrofit = new Retrofit.Builder() .baseUrl("https://api.github.com") .addConverterFactory(GsonConverterFactory.create()) .build(); GitHubService service = retrofit.create(GitHubService.class);
Retrofit实例的建立是主要是进行一些信息的配置,这里核心分析的在于其create方法,本篇文章的分析将会顺着create方法的实现到其最终一个网络请求的调用,同时结合着对Retrofit源码的分析来进一步展开对于Java中动态代理实现的分析。api
public <T> T create(final Class<T> service) { validateServiceInterface(service); return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class<?>[] { service }, new InvocationHandler() { private final Platform platform = Platform.get(); private final Object[] emptyArgs = new Object[0]; //对于代理中的继承自Object的方法还有平台方法直接invoke执行 @Override public @Nullable 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); } //对于其它咱们定义的方式调用loadServiceMethod return loadServiceMethod(method).invoke(args != null ? args : emptyArgs); } }); }
在Retrofit的实现中create是一个很关键的方法,也是咱们做为源码分析的一个切入点。首先看其第一个方法validateServiceInterface,该方法主要对传递的Service类进行校验,同时经过对注解的处理来获取到其中定义方法的相关信息。具体核心实现以下。缓存
for (Method method : service.getDeclaredMethods()) { if (!platform.isDefaultMethod(method) && !Modifier.isStatic(method.getModifiers())) { loadServiceMethod(method); } }
对于service中定义的方法进行遍历,而后经过调用loadServcieMethod进行相应的处理网络
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; }
loadServiceMethod方法是Retrofit的整个框架的实现的一个很核心的点了,首先会从ServiceMethodCache中进行相应的查找,若是查找到则直接返回,没有的话则会调用ServiceMethod的注解处理方法,parseAnnotaion来生成一个ServiceMethod,同时将其加入到缓存之中。那么接下来,咱们来看一下ServiceMethod的相关实现,和其注解解析方法。框架
static <T> ServiceMethod<T> parseAnnotations(Retrofit retrofit, Method method) { RequestFactory requestFactory = RequestFactory.parseAnnotations(retrofit, method); Type returnType = method.getGenericReturnType(); if (Utils.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); }
这里的核心实如今RequestFactory的parseAnnoations和HttpServiceMethod的parseAnnotations方法。接下咱们RequestFactory只是经过retorift和method构建了一个RequestFactory,记录了方法的参数,返回值类型还有注解信息。最后将其做为参数传递至HttpServiceMethod中的parseAnnotations,对于注解的处理主要是来将咱们在发送网络请求时须要的信息从注解中解析出来,当调用invoke方法的时候,结合解析出来的参数构建一个网络请求。ide
final ReturnT invoke(Object[] args) { Call<ResponseT> call = new OkHttpCall<>(requestFactory, args, callFactory, responseConverter); return adapt(call, args); }
在动态代理中当咱们进行一个方法调用的时候实际执行代码以下源码分析
loadServiceMethod(method).invoke(args != null ? args : emptyArgs);
对于loadServiceMethod方法,咱们以前已经分析过,这里主要根据方法解析的缓存中查找,而后调用其invoke方法,来构造一个OkHttp的请求。而后调用okhttp的相应的请求方法。学习
对于Rerofit在项目中的使用,最上层是咱们的业务逻辑,下面是咱们针对每个业务逻辑模块定义的API,第三层是Retrofit对于API层向网络请求OKhttp层的桥接,最终经过OkHttp将请求发送出去。同时其借助于注解与动态代理让代码的实现变的更优雅。借助于接口的形式来很好的实现网络请求在业务层的隔离。注解与动态代理搭配的形式对于后续的开发设计也是颇有启发意义的。ui