Retrofit核心流程分析
type
Post
status
Published
date
Dec 27, 2021
slug
retrofit
summary
来源:原创
tags
Android
category
码农
icon
password
基础使用
Retrofit retrofit = new Retrofit.Builder() .baseUrl("<http://fanyi.youdao.com/>") .addConverterFactory(GsonConverterFactory.create()) .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) .build(); GitHubService service = retrofit.create(GitHubService.class); Call call = (Call) service.getCall(); call.enqueue(new Callback() { @Override public void onFailure(Call call, IOException e) { } @Override public void onResponse(Call call, Response response) throws IOException { } });
public interface GitHubService { @GET(".../...") Call<List<MyResponse>> getCall(); }
Retrofit对象创建
从基础使用可知Retrofit对象的创建使用了Builder设计模式。
public Retrofit build() { if(this.baseUrl == null) { throw new IllegalStateException("Base URL required."); } else { Factory callFactory = this.callFactory; if(callFactory == null) { callFactory = new OkHttpClient(); } Executor callbackExecutor = this.callbackExecutor; if(callbackExecutor == null) { callbackExecutor = this.platform.defaultCallbackExecutor(); } List<retrofit2.CallAdapter.Factory> adapterFactories = new ArrayList(this.adapterFactories); adapterFactories.add(this.platform.defaultCallAdapterFactory(callbackExecutor)); List<retrofit2.Converter.Factory> converterFactories = new ArrayList(this.converterFactories); return new Retrofit((Factory)callFactory, this.baseUrl, converterFactories, adapterFactories, callbackExecutor, this.validateEagerly); } } }
build方法中我们添加CallAdatper和Converter列表,最后创建返回Retrofit对象。
创建Service
GitHubService service = retrofit.create(GitHubService.class);
public <T> T create(final Class<T> service) { Utils.validateServiceInterface(service); if(this.validateEagerly) { this.eagerlyValidateMethods(service); } return Proxy.newProxyInstance(service.getClassLoader(), new Class[]{service}, new InvocationHandler() { private final Platform platform = Platform.get(); public Object invoke(Object proxy, Method method, 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); //DefaultMethod 是 Java 8 的概念,是定义在 interface 当中的有实现的方法 } else if(this.platform.isDefaultMethod(method)) { return this.platform.invokeDefaultMethod(method, service, proxy, args); } else { //每一个接口最终实例化成一个 ServiceMethod,并且会缓存 ServiceMethod serviceMethod = Retrofit.this.loadServiceMethod(method); //由此可见 Retrofit 与 OkHttp 完全耦合,不可分割 OkHttpCall okHttpCall = new OkHttpCall(serviceMethod, args); //下面这一句当中会发起请求,并解析服务端返回的结果 return serviceMethod.callAdapter.adapt(okHttpCall); } } }); }
从create方法,我们发现retrofit使用了动态代理技术。首先会判断是否需要提前解析Service,这里我们先跳过,直接进入动态代理的代码。
由于我们在Android平台上使用,所以我们之间看最好三行代码:
ServiceMethod serviceMethod = Retrofit.this.loadServiceMethod(method); OkHttpCall okHttpCall = new OkHttpCall(serviceMethod, args); return serviceMethod.callAdapter.adapt(okHttpCall);
第一行:ServiceMethod
什么是ServiceMethod
其实根据该类的命名,我们就可以知道,这是Service接口中定义的一个方法的封装类,即:
@GET(".../...") Call<List<MyResponse>> getCall();
ServiceMethod(ServiceMethod.Builder<T> builder) { this.callFactory = builder.retrofit.callFactory(); this.callAdapter = builder.callAdapter; this.baseUrl = builder.retrofit.baseUrl(); this.responseConverter = builder.responseConverter; this.httpMethod = builder.httpMethod; this.relativeUrl = builder.relativeUrl; this.headers = builder.headers; this.contentType = builder.contentType; this.hasBody = builder.hasBody; this.isFormEncoded = builder.isFormEncoded; this.isMultipart = builder.isMultipart; this.parameterHandlers = builder.parameterHandlers; }
构造方法中我们可以明显ServiceMethod类封装后包含的变量信息。
loadServiceMethod
ServiceMethod loadServiceMethod(Method method) { Map var3 = this.serviceMethodCache; synchronized(this.serviceMethodCache) { ServiceMethod result = (ServiceMethod)this.serviceMethodCache.get(method); if(result == null) { result = (new retrofit2.ServiceMethod.Builder(this, method)).build(); this.serviceMethodCache.put(method, result); } return result; } }
首先我们会从缓存中获取ServiceMethod,如果获取不到,我们会创建一个,然后将新创建的ServiceMethod放到缓存列表中。
/** **为了代码更加清晰,减去了一些检测代码 **/ public ServiceMethod build() { //获取该Method对映的CallAdapter,详细代码见下述代码块 this.callAdapter = this.createCallAdapter(); this.responseType = this.callAdapter.responseType(); if(this.responseType != Response.class && this.responseType != okhttp3.Response.class) { //获取该Method对映的Converter,详细代码见下述代码块 this.responseConverter = this.createResponseConverter(); Annotation[] var1 = this.methodAnnotations; int p = var1.length; for(int var3 = 0; var3 < p; ++var3) { Annotation annotation = var1[var3]; this.parseMethodAnnotation(annotation); } int parameterCount = this.parameterAnnotationsArray.length; this.parameterHandlers = new ParameterHandler[parameterCount]; //循环解析Method中所以注解,存入parameterHandlers for(p = 0; p < parameterCount; ++p) { Type parameterType = this.parameterTypes[p]; Annotation[] parameterAnnotations = this.parameterAnnotationsArray[p]; this.parameterHandlers[p] = this.parseParameter(p, parameterType, parameterAnnotations); } return new ServiceMethod(this); } }
/** ** 根据method的返回值,从列表中获取对映的CallAdapter ** 减去检测代码 **/ private CallAdapter<?> createCallAdapter() { Type returnType = this.method.getGenericReturnType(); Annotation[] annotations = this.method.getAnnotations(); return this.retrofit.callAdapter(returnType, annotations); }
/** ** 根据responseType,从列表中获取对映的Converter ** 减去检测代码 **/ private Converter<ResponseBody, T> createResponseConverter() { Annotation[] annotations = this.method.getAnnotations(); return this.retrofit.responseBodyConverter(this.responseType, annotations); }
最后,还记得之前跳过的提前解析判断吗?
private void eagerlyValidateMethods(Class<?> service) { Platform platform = Platform.get(); Method[] var3 = service.getDeclaredMethods(); int var4 = var3.length; for(int var5 = 0; var5 < var4; ++var5) { Method method = var3[var5]; if(!platform.isDefaultMethod(method)) { this.loadServiceMethod(method); } } }
其实也就是提前调用了loadServiceMethod方法。
第二行:OkHttpCall
OkHttpCall okHttpCall = new OkHttpCall(serviceMethod, args);
第二行代码比较简单,就是创建了一个OkHttpCall对象,该对象内部实现了okhttp3对象创建,由此我们可知,Retrofit内部使用了okhttp来进行网络请求。
关于okhttp的流程分析,我看我的另一篇文章okhttp核心流程分析。
第三行:CallAdapter转换
return serviceMethod.callAdapter.adapt(okHttpCall);
通过适配器模式将 okHttpCall 转换成其他方式可用的形式,例如经典的Retrofit+RxJava, 默认 CallAdapter 使用其中的 Handler 将 Response 放到主线程中执行。
Call对象发起请求
最后通过okhttp3的Call对象发起网络请求。
Call call = (Call) service.getCall(); call.enqueue(new Callback() { @Override public void onFailure(Call call, IOException e) { } @Override public void onResponse(Call call, Response response) throws IOException { } });
下面方法即OkHttpCall从创建okttp3.Call的方法。
private okhttp3.Call createRawCall() throws IOException { Request request = this.serviceMethod.toRequest(this.args); okhttp3.Call call = this.serviceMethod.callFactory.newCall(request); if(call == null) { throw new NullPointerException("Call.Factory returned null."); } else { return call; } }
toRequest方法中我们可以看到retrofit将serviceMethod中的注解通过各种方式拼接成一个完善的Request。
Request toRequest(Object... args) throws IOException { RequestBuilder requestBuilder = new RequestBuilder(this.httpMethod, this.baseUrl, this.relativeUrl, this.headers, this.contentType, this.hasBody, this.isFormEncoded, this.isMultipart); ParameterHandler<Object>[] handlers = (ParameterHandler[])this.parameterHandlers; int argumentCount = args != null?args.length:0; if(argumentCount != handlers.length) { throw new IllegalArgumentException("Argument count (" + argumentCount + ") doesn't match expected count (" + handlers.length + ")"); } else { for(int p = 0; p < argumentCount; ++p) { handlers[p].apply(requestBuilder, args[p]); } return requestBuilder.build(); } }