.addConverterFactory(GsonConverterFactory.create(gson))
这样传回来的RespnseBody如果是个Json,那他就能转换成一个JavaBean。
我们就能把Api类的Call中的ResponseBody换成:
public interface GitHubService { @GET(“users/{user}/repos”) Call listRepos(@Path(“user”) String user); }
这就体现了Retrofit对响应体处理的强大。
我们来读Retrofit源码结构吧。
Retrofit大致源码解析
==============================================================================
enqueue
我们以下面代码为例子:
api.getRepo().enqueue(new Callback<List>() { @Override public void onResponse(Call<List> call, Response<List> response) { } @Override public void onFailure(Call<List> call, Throwable t) { } });
因为直接点进enqueue
它是Call的抽象方法,而getRepo
它也是个抽象方法,所以真正实现enqueue
方法的应该是api对象里面的。
api又是由retrofit.create(Api.class)
创建的,它创建了一个接口对象,所以我们去看create()方法,发现它终于是一个实现类了,也就是说这个方法它承接了后面所有的方法:
public T create(final Class 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 okHttpCall = new OkHttpCall<>(serviceMethod, args); return serviceMethod.callAdapter.adapt(okHttpCall); } }); }
Create()是整个Retrofit的核心
这个方法它创建出了一个ApiService的实例。ApiService明明是一个接口,却能实现了其声明的所有的网络请求。
这说明这个方法是真的很顶,能把你这个接口类的所有网络请求方法整的明明白白。
我们来一行一行的分析:
第一段:
Utils.validateServiceInterface(service);
从方法名可以看出,这个方是做验证的:验证传进来的ApiService,是不是一个Interface类,我们点进去看一下:
static void validateServiceInterface(Class service) { if (!service.isInterface()) { throw new IllegalArgumentException(“API declarations must be interfaces.”); } if (service.getInterfaces().length > 0) { throw new IllegalArgumentException(“API interfaces must not extend other interfaces.”); } }
是的,它首先会判断当前的类是不是一个Interface,其次它会判断当前的Interface有没有继承别的Interface,如果是的话就会抛出错误。
这个方法是做类型校验的,要求传进来的Interface类必须是原生的而且没有继承的。
第二段:
if (validateEagerly) { eagerlyValidateMethods(service); }
这也是一个验证,Eagerly是激进的意思,如果validateEagerly为true的话,Retrofiut会对ApiService做一个安全地、全面地验证,并且是在网络申请前做。这样的结果可能会导致程序卡一下, 而如果项目的Api很多,那我们在打开App的时候,它全都验证,那可能用户体验会极差。
所以我们一般都不会开这个玩意。
第三段
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 { … } });
看到了Proxy.newProxyInstance()
和里面的invoke()
方法,就是动态代理咯。
也就是可以认为在Retrofit中有一个代理类,专门帮我们配置这个Api信息。
至于动态代理,说到底就是 A对象有funcation()
这个方法可以去获取一些东西,可是当前情况不能直接通过A来执行funcation
方法,但是B对象可以做到,那我们通过给B对象设置 funcation()
方法,让B去帮我们获取这些东西。而这个代理方法的入口正是invoke()
动态代理的本质是Java的反射机制,你要弄懂动态代理,必须要先弄懂Java的反射,而我之前已经浅析过Java的反射机制,里面正好讲到了动态代理的例子,非常好理解。
链接在这里:Java反射机制
这里我讲细一点,这里有两个类,一个是代理类,一个是被代理类
- 被代理类
newProxyInstance()
中传入的第一个参数service.getClassLoader()
,获取service类的ClassLoader,这就说明service是被代理类,就是我们在retrofit.create(ApiService.class)的ApiService,它无法直接去执行网络请求,所以肯定有必要找代理类去帮我包装一下做事情。
- 代理类
代理类是newProxyInstance()
的最后一个参数,在这里就是new InvocationHandler() {...}
,它重写了invoke()
,invoke()就是实际的帮被代理类 去做网络请求的 方法,实际就是它来执行 listRepos()这个方法!!!!!!
到这里,我们就知道辽,整个return 返回的是一个动态代理类,当我们调用到网络请求的时候,这个动态代理类就会调用它的invoke方法。Ok那invoke方法里面具体是做什么的呢,我们来看一下。
invoke()方法
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 okHttpCall = new OkHttpCall<>(serviceMethod, args); return serviceMethod.callAdapter.adapt(okHttpCall); }
我们看下它的参数:
- Object proxy:代理类
- Method method:被代理的方法,比如ApiService的 listRepos()方法
- Object[] args:这个method的参数
了解完后我们来看下下面的内容,也分为三段:
part1:
if (method.getDeclaringClass() == Object.class) { //如果该方法是声明方法,则直接执行这个方法 return method.invoke(this, args); }
什么是声明方法呢?比如 MainActivity的onStart()、onResume或者toString()、onBackPressed()这种要么已经在自己类里面声明,要么在父类里面就声明的方法,则它会直接调用这个方法。
也就是说,如果我们的 网络请求 它已经被某个类给声明并且实现而不是在interface中,那么Retrofit就会直接执行它。
就是一个验证方法而已。保证我们用的方法是在interface接口中的。
part2
if (platform.isDefaultMethod(method)) { return platform.invokeDefaultMethod(method, service, proxy, args); }
对不同的Java平台会做不同的行为。
所以这个也比较一般,不用去了解。
part3 重点
ServiceMethod serviceMethod = (ServiceMethod) loadServiceMethod(method); OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args); return serviceMethod.callAdapter.adapt(okHttpCall);
第一行用 loadServiceMehotd()
来获取一个 ServiceMethod
,来看看它做了什么:
// CallAdapter.java ServiceMethod loadServiceMethod(Method method) { ServiceMethod result; synchronized (serviceMethodCache) { result = serviceMethodCache.get(method); // 获取缓存 serviceMethodCache是一个 ConcurrentHashMap结构 if (result == null) { result = new ServiceMethod.Builder(this, method).build(); // 如果没有缓存,就用build方法生成 serviceMethodCache.put(method, result); } } return result;
【附】相关架构及资料