🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
Retrofit 中创建 Service 接口访问实例就是通过动态代理实现的。 ~~~ 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);       }     }); } ~~~ 比如我们定义了 ~~~ public interface MovieService { @GET("top250") Call<MovieEntity> getTopMovie(@Query("start") int start, @Query("count") int count); } ~~~ 在这个 create 方法中,通过我们定义的 Service 接口,返回 MovieService 接口的代理对象。在执行到里面具体的 getTopMovie() 方法的时候,回去调用代理去执行方法的操作。最终会执行到这里的代码: ~~~ ServiceMethod<Object, Object> serviceMethod = (ServiceMethod<Object, Object>) loadServiceMethod(method); OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args); return serviceMethod.callAdapter.adapt(okHttpCall); ~~~ 第一行代码是根据本次传递进来的 getTopMovie 方法,去生成对应的 ServiceMethod 对象,然后缓存在本地的缓存map : serviceMethodCache中。 第二行根据对应的 serviceMethod 对象和传递进来的参数,生成 OkHttpCall 的实例,这个 OkHttpCall 内部封装了用于实际请求网络的 OkHttp 中的用于实际请求的 RealCall 对象。并且完成网路请求需要的请求信息的封装。 最终通过 CallAdapter 的 adapt 方法