源码分析Retrofit请求流程 (2)

这个 InvocationHandler 非常关键,当执行接口 Github 的contributors方法时,会委托给InvocationHandler的invoke 方法来执行。即Github将接口代理给了Proxy来执行了。

InvocationHandler

接着看InvocationHandler 接口的实现。

在 invoke 方法中有三个参数,其中proxy 就是代理对象,而 method 就是程序猿定义的那个网络请求接口,顾名思义 args 就是方法的参数。

此方法最终是调用了

loadServiceMethod(method).invoke(args != null ? args : emptyArgs); loadServiceMethod

打开 loadServiceMethod方法

ServiceMethod<?> loadServiceMethod(Method method) { // 判断是否有缓存 ServiceMethod<?> result = serviceMethodCache.get(method); if (result != null) return result; //同步处理 synchronized (serviceMethodCache) { result = serviceMethodCache.get(method); if (result == null) { //没有获取到缓存则使用`ServiceMethod`方法来创建 result = ServiceMethod.parseAnnotations(this, method); //最后缓存起来 serviceMethodCache.put(method, result); } } return result; }

这个方法就是通过 method 来获取一个 ServiceMethod 对象。

ServiceMethod

打开 ServiceMethod 发现它是一个抽象类,有一个静态方法 parseAnnotations 和一个抽象方法 invoke。

abstract class ServiceMethod<T> { 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."); } //最终使用到HttpServiceMethod类 return HttpServiceMethod.parseAnnotations(retrofit, method, requestFactory); } abstract T invoke(Object[] args); }

parseAnnotations 方法就是对程序猿定义的接口中使用的注解进行解析。

最后是使用了HttpServiceMethod.parseAnnotations方法

HttpServiceMethod /** Adapts an invocation of an interface method into an HTTP call. */ final class HttpServiceMethod<ResponseT, ReturnT> extends ServiceMethod<ReturnT> { static <ResponseT, ReturnT> HttpServiceMethod<ResponseT, ReturnT> parseAnnotations( Retrofit retrofit, Method method, RequestFactory requestFactory) { CallAdapter<ResponseT, ReturnT> callAdapter = createCallAdapter(retrofit, method); //...省略部分代码 Converter<ResponseBody, ResponseT> responseConverter = createResponseConverter(retrofit, method, responseType); okhttp3.Call.Factory callFactory = retrofit.callFactory; return new HttpServiceMethod<>(requestFactory, callFactory, callAdapter, responseConverter); } //...省略部分代码 @Override ReturnT invoke(Object[] args) { return callAdapter.adapt( new OkHttpCall<>(requestFactory, args, callFactory, responseConverter)); } }

HttpServiceMethod 是 ServiceMethod 的子类。而在parseAnnotations 方法中构造了HttpServiceMethod实例并返回。

因此,loadServiceMethod方法返回的是HttpServiceMehod对象

这样下面代码的执行实际上是执行了 HttpServiceMehod 的 invoke 方法。

loadServiceMethod(method).invoke(args != null ? args : emptyArgs);

再次翻看上文中HttpServiceMethod类

@Override ReturnT invoke(Object[] args) { return callAdapter.adapt( new OkHttpCall<>(requestFactory, args, callFactory, responseConverter)); }

invoke 方法里有执行了callAdapter.adapt方法,参数为OkHttpCall,这个类实际上就是对okhttp网络请求的封装,这里也可以看出retrofit内部是使用了okhttp来执行网络请求的

CallAdapter public interface CallAdapter<R, T> { //..省略部分代码 T adapt(Call<R> call); //CallAdapter抽象工厂类 abstract class Factory { //返回CallAdapter实例 public abstract @Nullable CallAdapter<?, ?> get(Type returnType, Annotation[] annotations, Retrofit retrofit); //..省略部分代码 } }

这是一个接口,内部有一个Factory抽象工厂类,用于获取CallAdapter对象。

CallAdapter 有很多子类,那 callAdapter.adapt 方法执行的是哪个具体类的方法呢?实际上,从调试代码中可以发现是调用DefaultCallFactory中的内部实现类

源码分析Retrofit请求流程

DefaultCallAapterFactory final class DefaultCallAdapterFactory extends CallAdapter.Factory { static final CallAdapter.Factory INSTANCE = new DefaultCallAdapterFactory(); @Override public @Nullable CallAdapter<?, ?> get( Type returnType, Annotation[] annotations, Retrofit retrofit) { if (getRawType(returnType) != Call.class) { return null; } final Type responseType = Utils.getCallResponseType(returnType); //返回一个CallAapter实例 return new CallAdapter<Object, Call<?>>() { @Override public Type responseType() { return responseType; } @Override public Call<Object> adapt(Call<Object> call) { //将参数返回,而这个参数就是OKHttpCall的实例 return call; } }; } }

可以发现,在adapt方法中就是将参数call返回。

所以下面代码返回的是OkHttpCall对象。

loadServiceMethod(method).invoke(args != null ? args : emptyArgs);

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zwzgff.html