Retrofit简介 retrofit
n. 式样翻新,花样翻新 vt. 给机器设备装配(新部件),翻新,改型
Retrofit 是一个 RESTful 的 HTTP 网络请求框架的封装。注意这里并没有说它是网络请求框架,主要原因在于网络请求的工作并不是 Retrofit
来完成的。Retrofit
2.0 开始内置 OkHttp
,前者专注于接口的封装,后者专注于真正的网络请求。即通过 大量的设计模式 封装了 OkHttp
,使得简洁易用。
我们的应用程序通过 Retrofit
请求网络,实际上是使用 Retrofit
接口层封装请求参数、Header、Url 等信息,之后由 OkHttp
完成后续的请求操作,在服务端返回数据之后,OkHttp
将原始的结果交给 Retrofit
,后者根据用户的需求对结果进行解析的过程。Retrofit的大概原理过程如下:
Retrofit
将 Http
请求 抽象 成 Java
接口
在接口里用 注解 描述和配置 网络请求参数
用动态代理 的方式,动态将网络请求接口的注解 解析 成HTTP
请求
最后执行HTTP
请求
这篇文章我将从Retrofit的基本用法出发,按照其使用步骤,一步步的探究Retrofit的实现原理及其源码的设计模式。
Retrofit Github: https://github.com/square/retrofit
使用步骤 使用 Retrofit
非常简单,首先需要在 build.gradle 中添加依赖:
1 implementation 'com.squareup.retrofit2:retrofit:2.4.0'
如果需要使用Gson解析器,也需要在build.gradle中添加依赖(后文会详细讲到Retrofit的Converter):
1 implementation 'com.squareup.retrofit2:converter-gson:2.0.2'
1. 定义Interface Retrofit使用java interface和注解描述了HTTP请求的API参数,比如Github的一个API:
1 2 3 4 public interface GitHubService { @GET ("users/{user}/repos" ) Call<List<Repo>> listRepos(@Path ("user" ) String user); }
其中Repo类定义如下:
1 2 3 4 5 6 7 8 9 10 11 public class Repo { public String name; public String getName () { return name; } public void setName (String name) { this .name = name; } }
2. 创建Retrofit实例 这样调用Retrofit就会为上面这个interface自动生成一个实现类:
1 2 3 4 5 6 Retrofit retrofit = new Retrofit.Builder() .baseUrl("https://api.github.com/" ) .addConverterFactory(GsonConverterFactory.create()) .build(); GitHubService service = retrofit.create(GitHubService.class);
3. 发起请求 然后调用interface的具体方法时(这里是listRepos()
)就构造好了一个Call
,
1 Call<List<Repo>> call = service.listRepos("octocat" );
返回的 call
其实并不是真正的数据结果,只是封装成了一个随时可以执行的请求,需要在合适的时机去执行它:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 List<Repo> data = repos.execute(); repos.enqueue(new Callback<List<Repo>>() { @Override public void onResponse (Call<List<Repo>> call, Response<List<Repo>> response) { List<Repo> data = response.body(); } @Override public void onFailure (Call<List<Repo>> call, Throwable t) { t.printStackTrace(); } });
怎么样,有没有突然觉得请求接口就好像访问自家的方法一样简单?下面我们转入源码分析,按照使用步骤来探索Retrofit的实现原理。
源码分析 我们先来看看Retrofit的实例化步骤。先看看Retrofit这个类的参数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 public final class Retrofit { private final Map<Method, ServiceMethod<?, ?>> serviceMethodCache = new ConcurrentHashMap<>(); final okhttp3.Call.Factory callFactory; final HttpUrl baseUrl; final List<Converter.Factory> converterFactories; final List<CallAdapter.Factory> callAdapterFactories; final @Nullable Executor callbackExecutor; final boolean validateEagerly; Retrofit(okhttp3.Call.Factory callFactory, HttpUrl baseUrl, List<Converter.Factory> converterFactories, List<CallAdapter.Factory> callAdapterFactories, @Nullable Executor callbackExecutor, boolean validateEagerly) { this .callFactory = callFactory; this .baseUrl = baseUrl; this .converterFactories = converterFactories; this .callAdapterFactories = callAdapterFactories; this .callbackExecutor = callbackExecutor; this .validateEagerly = validateEagerly; } }
Retrofit的构造函数是package包可见的,并不是public的,所以外部并不能直接new,而是要通过Retrofit.Builder
来实例化。
Retrofit.Builder Retrofit.Builder
是 Retrofit 类中的一个子类,负责用来创建 Retrofit 实例对象,使用『Builder模式』的好处是清晰明了可定制化。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 public static final class Builder { private final Platform platform; private @Nullable okhttp3.Call.Factory callFactory; private HttpUrl baseUrl; private final List<Converter.Factory> converterFactories = new ArrayList<>(); private final List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>(); private @Nullable Executor callbackExecutor; private boolean validateEagerly; Builder(Platform platform) { this .platform = platform; } public Builder () { this (Platform.get()); } }
可以看到Retrofit.Builder
中的成员变量跟Retrofit中基本上是一一对应的,就不过多解释了。这里可以看到Builder的构造函数中默认判断了一下当前的运行平台。
最后,在创建 Retrofit.Builder
对象并进行自定义配置后,我们就要调用 build()
方法来构造出 Retrofit
对象了。那么,我们来看下 build()
方法里干了什么:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 public Retrofit build () { if (baseUrl == null ) { throw new IllegalStateException("Base URL required." ); } okhttp3.Call.Factory callFactory = this .callFactory; if (callFactory == null ) { callFactory = new OkHttpClient(); } Executor callbackExecutor = this .callbackExecutor; if (callbackExecutor == null ) { callbackExecutor = platform.defaultCallbackExecutor(); } List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>(this .callAdapterFactories); callAdapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor)); List<Converter.Factory> converterFactories = new ArrayList<>(1 + this .converterFactories.size()); converterFactories.add(new BuiltInConverters()); converterFactories.addAll(this .converterFactories); return new Retrofit(callFactory, baseUrl, unmodifiableList(converterFactories), unmodifiableList(callAdapterFactories), callbackExecutor, validateEagerly); }
在 build()
中,做的事情有:检查配置、设置默认配置、创建 Retrofit
对象。并且在执行 .build()
方法前,只有 .baseUrl()
是必须调用来设置访问地址的,其余方法则是可选的。同时我们可以看到设置了很多默认成员,但这里我们重点关注四个成员:callFactory
,callAdapter
,responseConverter
和 parameterHandlers
。
callFactory
负责创建 HTTP 请求,HTTP 请求被抽象为了 okhttp3.Call
类,它表示一个已经准备好,可以随时执行的 HTTP 请求;
callAdapter
负责把 retrofit2.Call<?>
里的Call
转换为 另一种类型T
(注意和 okhttp3.Call
区分开来,retrofit2.Call<?>
表示的是对一个 Retrofit 方法的调用),这个过程会发送一个 HTTP 请求,拿到服务器返回的数据(通过 okhttp3.Call
实现),并把数据转换为声明的 T
类型对象(通过 Converter<F, T>
实现);
responseConverter
是 Converter<ResponseBody, T>
类型,负责把服务器返回的数据(JSON、XML、PB、二进制或者其他格式,由 ResponseBody
封装)转化为 T
类型的对象;
parameterHandlers
则负责解析 API 定义时每个方法的参数,并在构造 HTTP 请求时设置参数;
CallAdapter和Converter到底是干什么的? 这里多插两句,给大家解释一下这个CallAdapter
和Converter
到底是干什么的?我们知道,最简单的Retrofit接口一般定义如下:
1 2 3 4 public interface GitHubService { @GET ("users/{user}/repos" ) Call<ResponseBody> listRepos (@Path("user" ) String user) ; }
在给Retrofit不添加任何CallAdapterFactory
的情况下,接口方法的返回类型必须是Call<?>
,不能是其他类型。因而Retrofit提供了对这个Call进行转换为其他类型的功能,那就是CallAdapter
。比如添加一个RxJava 的CallAdapter:
1 2 3 4 Retrofit retrofit = new Retrofit.Builder() .baseUrl("https://api.example.com" ) .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) .build();
然后我们就可以这样定义接口:
1 2 3 4 interface MyService { @GET ("/user" ) Observable<User> getUser () ; }
如果添加了一个Java8 的CallAdapter,就可以这样定义接口:
1 2 3 4 interface MyService { @GET ("/user" ) CompletableFuture<User> getUser () ; }
Retrofit提供的CallAdapter:
CallAdapter
Gradle依赖
guava
com.squareup.retrofit2:adapter-guava:latest.version
Java8
com.squareup.retrofit2:adapter-java8:latest.version
rxjava
com.squareup.retrofit2:adapter-rxjava:latest.version
rxjava2
com.squareup.retrofit2:adapter-rxjava2:latest.version
scala
com.squareup.retrofit2:adapter-scala:latest.version
同样地,如果在不给Retrofit添加任何ConverterFactory
的情况下,接口方法返回类型Call<T>
里的泛型T
必须是ResponseBody
,而不能是其他类型(比如List<User>
),这就是Converter
的作用,直白点也就是数据解析器,负责把ResponseBody
解析成List<User>
。
另外,在我们构造 HTTP 请求时,我们传递的参数都是使用的注解类型(诸如 Path
,Query
,Field
等),那 Retrofit 是如何把我们传递的各种参数都转化为 String 的呢?还是由 Retrofit
类提供Converter
!
Converter.Factory
除了提供responseBodyConverter,还提供 requestBodyConverter 和 stringConverter,API 方法中除了 @Body
和 @Part
类型的参数,都利用 stringConverter 进行转换,而 @Body
和 @Part
类型的参数则利用 requestBodyConverter 进行转换。
Retrofit提供的Converter
Converter
Gradle依赖
Gson
com.squareup.retrofit2:converter-gson:latest.version
Guava
com.squareup.retrofit2:converter-guava:latest.version
Jackson
com.squareup.retrofit2:converter-jackson:latest.version
Java8
com.squareup.retrofit2:converter-java8:latest.version
Jaxb
com.squareup.retrofit2:converter-jaxb:latest.version
Moshi
com.squareup.retrofit2:converter-moshi:latest.version
Protobuf
com.squareup.retrofit2:converter-protobuf:latest.version
Scalars
com.squareup.retrofit2:converter-scalars:latest.version
Wire
com.squareup.retrofit2:converter-wire:latest.version
Simple XML
com.squareup.retrofit2:converter-simplexml:latest.version
这里我们再来个小插曲,来看下 Retrofit 是如何确定当前运行的是哪个平台环境的。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 class Platform { private static final Platform PLATFORM = findPlatform(); static Platform get () { return PLATFORM; } private static Platform findPlatform () { try { Class.forName("android.os.Build" ); if (Build.VERSION.SDK_INT != 0 ) { return new Android(); } } catch (ClassNotFoundException ignored) { } try { Class.forName("java.util.Optional" ); return new Java8(); } catch (ClassNotFoundException ignored) { } return new Platform(); } @Nullable Executor defaultCallbackExecutor () { return null ; } CallAdapter.Factory defaultCallAdapterFactory (@Nullable Executor callbackExecutor) { if (callbackExecutor != null ) { return new ExecutorCallAdapterFactory(callbackExecutor); } return DefaultCallAdapterFactory.INSTANCE; } boolean isDefaultMethod (Method method) { return false ; } @Nullable Object invokeDefaultMethod (Method method, Class<?> declaringClass, Object object, @Nullable Object... args) throws Throwable { throw new UnsupportedOperationException(); } }
从上面的代码中可以看到,是通过反射判断有没有该类来实现的。比较巧妙,大家可以的学习一下。
而此处的Android
和Java8
均是Platform的子类:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 static class Android extends Platform { @Override public Executor defaultCallbackExecutor () { return new MainThreadExecutor(); } @Override CallAdapter.Factory defaultCallAdapterFactory (@Nullable Executor callbackExecutor) { if (callbackExecutor == null ) throw new AssertionError(); return new ExecutorCallAdapterFactory(callbackExecutor); } static class MainThreadExecutor implements Executor { private final Handler handler = new Handler(Looper.getMainLooper()); @Override public void execute (Runnable r) { handler.post(r); } } }
Java8的定义如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 @IgnoreJRERequirement static class Java8 extends Platform { @Override boolean isDefaultMethod (Method method) { return method.isDefault(); } @Override Object invokeDefaultMethod (Method method, Class<?> declaringClass, Object object, @Nullable Object... args) throws Throwable { Constructor<Lookup> constructor = Lookup.class.getDeclaredConstructor(Class.class, int .class); constructor.setAccessible(true ); return constructor.newInstance(declaringClass, -1 ) .unreflectSpecial(method, declaringClass) .bindTo(object) .invokeWithArguments(args); } }
Java 8 的interface引入了新的语言特性——默认方法(Default Methods)。大家可以参考这篇文章:Java8 默认方法 default method
默认方法允许您添加新的功能到现有库的接口中,并能确保与采用旧版本接口编写的代码的二进制兼容性。
所以如果在Java8的平台上使用Retrofit的话,Retrofit需要排除我们定义的interface中的这些Default Methods。
在使用Retrofit.Builder
实例化得到 Retrofit
对象后就是调用 Retrofit#create()
方法来创建我们 API 接口的实例。
Retrofit 所以我们需要跟进Retrofit类中的 create(final Class<T> service)
方法来看下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 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, Object... args) throws Throwable { if (method.getDeclaringClass() == Object.class) { return method.invoke(this , args); } if (platform.isDefaultMethod(method)) { return platform.invokeDefaultMethod(method, service, proxy, args); } ServiceMethod serviceMethod = loadServiceMethod(method); OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args); return serviceMethod.callAdapter.adapt(okHttpCall); } }); }
在上面的代码中,最关键的就是『动态代理』,返回了一个 Proxy 代理类,调用接口中的任何方法都会调用 proxy 里的 invoke 方法。实际上,进行网络操作的都是通过代理类来完成的。简单的说,在我们前面的示例代码中调用 GitHubService.listRepos
时,实际上调用的是这里的 InvocationHandler.invoke
方法。
InvocationHandler.invoke
这个方法的意思是:如果调用的是 Object
的方法,例如 equals
,toString
,那就直接调用。如果是 default 方法(Java 8 引入的新语法),就调用 default 方法。这些我们都先不管,因为我们在Android平台调用 listRepos
,肯定不是这两种情况,那这次调用真正干活的就是这三行代码了:
1 2 3 4 ServiceMethod<Object, Object> serviceMethod = (ServiceMethod<Object, Object>) loadServiceMethod(method); OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args); return serviceMethod.adapt(okHttpCall);
这三句代码,下面我们着重来看。
在代理中,会根据参数中传入的具体接口方法来构造出对应的 serviceMethod
。ServiceMethod
类的作用就是把接口的方法适配为对应的 HTTP call 。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 ServiceMethod<?, ?> loadServiceMethod(Method method) { ServiceMethod<?, ?> result = serviceMethodCache.get(method); if (result != null ) return result; synchronized (serviceMethodCache) { result = serviceMethodCache.get(method); if (result == null ) { result = new ServiceMethod.Builder<>(this , method).build(); serviceMethodCache.put(method, result); } } return result; }
可以看到在内部还维护了一个 serviceMethodCache
来缓存 ServiceMethod
,同一个 API 的同一个方法,只会创建一次。由于我们每次获取 API 实例都是传入的 class
对象(比如示例中的GitHubService.class),而 class
对象是进程内单例的,所以获取到它的同一个方法 Method
实例也是单例的,所以这里的缓存是有效的。我们就直接来看 ServiceMethod
是如何被创建的吧。
ServiceMethod ServiceMethod<R, T>
类的作用正如其 JavaDoc 所言:
Adapts an invocation of an interface method into an HTTP call. 把对接口方法的调用转为一次 HTTP 调用。
一个 ServiceMethod
对象对应于一个 API interface 的一个方法,上面的loadServiceMethod(method)
方法负责加载了 ServiceMethod
。我们发现 ServiceMethod
也是通过建造者模式(ServiceMethod.Builder
)来创建对象的。那就进入对应构造方法:
1 2 3 4 5 6 7 8 9 10 11 Builder(Retrofit retrofit, Method method) { this .retrofit = retrofit; this .method = method; this .methodAnnotations = method.getAnnotations(); this .parameterTypes = method.getGenericParameterTypes(); this .parameterAnnotationsArray = method.getParameterAnnotations(); }
在构造方法中没有什么特别的地方,我们单刀直入 build()
方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 public ServiceMethod build () { callAdapter = createCallAdapter(); responseType = callAdapter.responseType(); if (responseType == Response.class || responseType == okhttp3.Response.class) { throw methodError("'" + Utils.getRawType(responseType).getName() + "' is not a valid response body type. Did you mean ResponseBody?" ); } responseConverter = createResponseConverter(); for (Annotation annotation : methodAnnotations) { parseMethodAnnotation(annotation); } if (httpMethod == null ) { throw methodError("HTTP method annotation is required (e.g., @GET, @POST, etc.)." ); } if (!hasBody) { if (isMultipart) { throw methodError( "Multipart can only be specified on HTTP methods with request body (e.g., @POST)." ); } if (isFormEncoded) { throw methodError("FormUrlEncoded can only be specified on HTTP methods with " + "request body (e.g., @POST)." ); } } int parameterCount = parameterAnnotationsArray.length; parameterHandlers = new ParameterHandler<?>[parameterCount]; for (int p = 0 ; p < parameterCount; p++) { Type parameterType = parameterTypes[p]; if (Utils.hasUnresolvableType(parameterType)) { throw parameterError(p, "Parameter type must not include a type variable or wildcard: %s" , parameterType); } Annotation[] parameterAnnotations = parameterAnnotationsArray[p]; if (parameterAnnotations == null ) { throw parameterError(p, "No Retrofit annotation found." ); } parameterHandlers[p] = parseParameter(p, parameterType, parameterAnnotations); } if (relativeUrl == null && !gotUrl) { throw methodError("Missing either @%s URL or @Url parameter." , httpMethod); } if (!isFormEncoded && !isMultipart && !hasBody && gotBody) { throw methodError("Non-body HTTP method cannot contain @Body." ); } if (isFormEncoded && !gotField) { throw methodError("Form-encoded method must contain at least one @Field." ); } if (isMultipart && !gotPart) { throw methodError("Multipart method must contain at least one @Part." ); } return new ServiceMethod<>(this ); }
在 build()
中代码挺长的,总结起来就一句话:就是将 API 接口中的方法进行解析,构造成 ServiceMethod
,交给下面的 OkHttpCall
使用。
基本上做的事情就是:
创建 CallAdapter ;
创建 ResponseConverter;
根据 API 接口方法的注解构造网络请求方法;
根据 API 接口方法参数中的注解构造网络请求的参数;
检查有无异常;
下面我们看看第二句重要的代码OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
OkHttpCall OkHttpCall
实现了 retrofit2.Call
,我们通常会使用它的 execute()
和 enqueue(Callback<T> callback)
接口。前者用于同步执行 HTTP 请求,后者用于异步执行。我们先看 execute()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 @Override public Response<T> execute () throws IOException { okhttp3.Call call; synchronized (this ) { if (executed) throw new IllegalStateException("Already executed." ); executed = true ; if (creationFailure != null ) { if (creationFailure instanceof IOException) { throw (IOException) creationFailure; } else if (creationFailure instanceof RuntimeException) { throw (RuntimeException) creationFailure; } else { throw (Error) creationFailure; } } call = rawCall; if (call == null ) { try { call = rawCall = createRawCall(); } catch (IOException | RuntimeException | Error e) { throwIfFatal(e); creationFailure = e; throw e; } } } if (canceled) { call.cancel(); } return parseResponse(call.execute()); }
在 execute()
做的就是将 Retrofit 中的 call 转化为 OkHttp 中的 Call 。最后让 OkHttp 的 Call 去执行。
主要包括三步:
调用createRawCall()
创建了 okhttp3.Call
,包括构造参数;
使用call.execute()
执行网络请求;
解析网络请求返回的数据;
我们分别来看看createRawCall()
和parseResponse()
这两个方法:
1 2 3 4 5 6 7 8 private okhttp3.Call createRawCall () throws IOException { okhttp3.Call call = serviceMethod.toCall(args); if (call == null ) { throw new NullPointerException("Call.Factory returned null." ); } return call; }
createRawCall()
函数中,我们调用了 serviceMethod.toCall(args)
来创建 okhttp3.Call
,而在后者中,我们之前准备好的 parameterHandlers
就派上了用场。
然后我们再调用 serviceMethod.callFactory.newCall(request)
来创建 okhttp3.Call
,这里之前准备好的 callFactory
同样也派上了用场,由于工厂在构造 Retrofit
对象时可以指定,所以我们也可以指定其他的工厂(例如使用过时的 HttpURLConnection
的工厂),来使用其它的底层 HttpClient 实现。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 Response<T> parseResponse (okhttp3.Response rawResponse) throws IOException { ResponseBody rawBody = rawResponse.body(); rawResponse = rawResponse.newBuilder() .body(new NoContentResponseBody(rawBody.contentType(), rawBody.contentLength())) .build(); int code = rawResponse.code(); if (code < 200 || code >= 300 ) { try { ResponseBody bufferedBody = Utils.buffer(rawBody); return Response.error(bufferedBody, rawResponse); } finally { rawBody.close(); } } if (code == 204 || code == 205 ) { rawBody.close(); return Response.success(null , rawResponse); } ExceptionCatchingRequestBody catchingBody = new ExceptionCatchingRequestBody(rawBody); try { T body = serviceMethod.toResponse(catchingBody); return Response.success(body, rawResponse); } catch (RuntimeException e) { catchingBody.throwIfCaught(); throw e; } }
我们调用 okhttp3.Call#execute()
来执行网络请求,这个方法是阻塞的,执行完毕之后将返回收到的响应数据。收到响应数据之后,我们进行了状态码的检查,通过检查之后我们调用了 serviceMethod.toResponse(catchingBody)
来把响应数据转化为了我们需要的数据类型对象T。
1 2 3 4 R toResponse (ResponseBody body) throws IOException { return responseConverter.convert(body); }
在serviceMethod
的toResponse
函数中,我们之前准备好的 responseConverter
也派上了用场。我们分别看下:
responseConverter
这个实例哪里来?
ResponseConverter
的convert()
方法干了什么?
默认的Converter #1. responseConverter
这个实例哪里来? 在ServiceMethod.Builder
类中,我们找到了它的赋值的地方:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 public ServiceMethod build () { callAdapter = createCallAdapter(); responseType = callAdapter.responseType(); if (responseType == Response.class || responseType == okhttp3.Response.class) { throw methodError("'" + Utils.getRawType(responseType).getName() + "' is not a valid response body type. Did you mean ResponseBody?" ); } responseConverter = createResponseConverter(); }
很明显,在build()
方法中同时创建了默认的CallAdapter和ResponseConverter。我们先继续前往createResponseConverter
关注ResponseConverter:
1 2 3 4 5 6 7 8 private Converter<ResponseBody, T> createResponseConverter () { Annotation[] annotations = method.getAnnotations(); try { return retrofit.responseBodyConverter(responseType, annotations); } catch (RuntimeException e) { throw methodError(e, "Unable to create converter for %s" , responseType); } }
原来是根据我们定义的接口方法的返回类型和注解,交给了Retrofit的responseBodyConverter(Type type, Annotation[] annotations)
去找:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 public <T> Converter<ResponseBody, T> responseBodyConverter (Type type, Annotation[] annotations) { return nextResponseBodyConverter(null , type, annotations); } public <T> Converter<ResponseBody, T> nextResponseBodyConverter ( @Nullable Converter.Factory skipPast, Type type, Annotation[] annotations) { checkNotNull(type, "type == null" ); checkNotNull(annotations, "annotations == null" ); int start = converterFactories.indexOf(skipPast) + 1 ; for (int i = start, count = converterFactories.size(); i < count; i++) { Converter<ResponseBody, ?> converter = converterFactories.get(i).responseBodyConverter(type, annotations, this ); if (converter != null ) { return (Converter<ResponseBody, T>) converter; } } StringBuilder builder = new StringBuilder("Could not locate ResponseBody converter for " ) .append(type) .append(".\n" ); if (skipPast != null ) { builder.append(" Skipped:" ); for (int i = 0 ; i < start; i++) { builder.append("\n * " ).append(converterFactories.get(i).getClass().getName()); } builder.append('\n' ); } builder.append(" Tried:" ); for (int i = start, count = converterFactories.size(); i < count; i++) { builder.append("\n * " ).append(converterFactories.get(i).getClass().getName()); } throw new IllegalArgumentException(builder.toString()); }
在 Retrofit
类内部,将遍历一个 converterFactories
列表,让工厂们提供,如果最终没有工厂能(根据 returnType
和 annotations
)提供需要的 ResponseConverter
,那将抛出异常。而这个工厂列表我们可以在构造 Retrofit
对象时进行添加。
还记得我们在使用Retrofit.Builder
构造Retrofit对象的时候,默认添加的converterFactory
吗?
1 2 3 4 5 6 7 8 9 10 11 12 public Retrofit build () { converterFactories.add(new BuiltInConverters()); converterFactories.addAll(this .converterFactories); return new Retrofit(callFactory, baseUrl, unmodifiableList(converterFactories), unmodifiableList(callAdapterFactories), callbackExecutor, validateEagerly); }
#2. ResponseConverter
的convert()
方法干了什么? 我们看看这个内置转换器(BuildInConverters
)是什么东西:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 final class BuiltInConverters extends Converter .Factory { @Override public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations, Retrofit retrofit) { if (type == ResponseBody.class) { return Utils.isAnnotationPresent(annotations, Streaming.class) ? StreamingResponseBodyConverter.INSTANCE : BufferingResponseBodyConverter.INSTANCE; } if (type == Void.class) { return VoidResponseBodyConverter.INSTANCE; } return null ; } @Override public Converter<?, RequestBody> requestBodyConverter(Type type, Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) { if (RequestBody.class.isAssignableFrom(Utils.getRawType(type))) { return RequestBodyConverter.INSTANCE; } return null ; } static final class StreamingResponseBodyConverter implements Converter <ResponseBody , ResponseBody > { static final StreamingResponseBodyConverter INSTANCE = new StreamingResponseBodyConverter(); @Override public ResponseBody convert (ResponseBody value) { return value; } } }
内置的BuiltInConverters
会直接返回ResponseBody
或者Void
类型,不做其他任何的转换操作,所以如果我们不添加任何ConverterFactory的默认情况下,我们定义的接口方法返回类型只能接受ResponseBody
或者Void
这两种类型。
默认的CallAdapter 下面,我们来看下那三句重要代码中的最后一句return serviceMethod.adapt(okHttpCall);
。ServiceMethod类中的adapt()
方法如下:
1 2 3 4 T adapt (Call<R> call) { return callAdapter.adapt(call); }
这里我们分别看下:
这个callAdapter
实例哪里来的?
CallAdapter
类的adapt()
方法干了什么?
#1. 这个callAdapter
实例哪里来的? 这个callAdapter
实例是在哪里赋值的呢,我们找到了ServiceMethod.Builder
的build()
方法,可以回到上面看看这个方法的源码,可以看到它是调用了createCallAdapter
这个方法创建的,如下。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 private CallAdapter<T, R> createCallAdapter () { Type returnType = method.getGenericReturnType(); if (Utils.hasUnresolvableType(returnType)) { throw methodError( "Method return type must not include a type variable or wildcard: %s" , returnType); } if (returnType == void .class) { throw methodError("Service methods cannot return void." ); } Annotation[] annotations = method.getAnnotations(); try { return (CallAdapter<T, R>) retrofit.callAdapter(returnType, annotations); } catch (RuntimeException e) { throw methodError(e, "Unable to create call adapter for %s" , returnType); } }
可以看到,callAdapter
还是由 Retrofit
类提供的。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 public CallAdapter<?, ?> callAdapter(Type returnType, Annotation[] annotations) { return nextCallAdapter(null , returnType, annotations); } public CallAdapter<?, ?> nextCallAdapter(@Nullable CallAdapter.Factory skipPast, Type returnType, Annotation[] annotations) { checkNotNull(returnType, "returnType == null" ); checkNotNull(annotations, "annotations == null" ); int start = callAdapterFactories.indexOf(skipPast) + 1 ; for (int i = start, count = callAdapterFactories.size(); i < count; i++) { CallAdapter<?, ?> adapter = callAdapterFactories.get(i).get(returnType, annotations, this ); if (adapter != null ) { return adapter; } } StringBuilder builder = new StringBuilder("Could not locate call adapter for " ) .append(returnType) .append(".\n" ); if (skipPast != null ) { builder.append(" Skipped:" ); for (int i = 0 ; i < start; i++) { builder.append("\n * " ).append(callAdapterFactories.get(i).getClass().getName()); } builder.append('\n' ); } builder.append(" Tried:" ); for (int i = start, count = callAdapterFactories.size(); i < count; i++) { builder.append("\n * " ).append(callAdapterFactories.get(i).getClass().getName()); } throw new IllegalArgumentException(builder.toString()); }
在 Retrofit
类内部,将遍历一个 CallAdapter.Factory
列表,让工厂们提供,如果最终没有工厂能(根据 returnType
和 annotations
)提供需要的 CallAdapter
,那将抛出异常。而这个工厂列表我们可以在构造 Retrofit
对象时进行添加。
还记得我们在使用Retrofit.Builder
构造Retrofit对象的时候,默认添加的CallAdapterFactory
吗?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 public Retrofit build () { List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>(this .callAdapterFactories); callAdapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor)); return new Retrofit(callFactory, baseUrl, unmodifiableList(converterFactories), unmodifiableList(callAdapterFactories), callbackExecutor, validateEagerly); } }
而此时的Platform是Android
,回顾一下Android的默认CallAdapterFactory:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 static class Android extends Platform { @Override public Executor defaultCallbackExecutor () { return new MainThreadExecutor(); } @Override CallAdapter.Factory defaultCallAdapterFactory (@Nullable Executor callbackExecutor) { if (callbackExecutor == null ) throw new AssertionError(); return new ExecutorCallAdapterFactory(callbackExecutor); } static class MainThreadExecutor implements Executor { private final Handler handler = new Handler(Looper.getMainLooper()); @Override public void execute (Runnable r) { handler.post(r); } } }
可以看到默认的是ExecutorCallAdapterFactory
这个工厂类,
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 final class ExecutorCallAdapterFactory extends CallAdapter .Factory { final Executor callbackExecutor; ExecutorCallAdapterFactory(Executor callbackExecutor) { this .callbackExecutor = callbackExecutor; } @Override public CallAdapter<?, ?> get(Type returnType, Annotation[] annotations, Retrofit retrofit) { if (getRawType(returnType) != Call.class) { return null ; } final Type responseType = Utils.getCallResponseType(returnType); return new CallAdapter<Object, Call<?>>() { @Override public Type responseType () { return responseType; } @Override public Call<Object> adapt (Call<Object> call) { return new ExecutorCallbackCall<>(callbackExecutor, call); } }; } }
可以看到ExecutorCallAdapterFactory
这个工厂类通过get()
方法new了一个CallAdapter
。然后来看看第二个问题。
#2. CallAdapter
类的adapt()
方法干了什么? 好了,搞清楚了callAdapter
的来历,我们看看它的adapt()
方法。从上面的分析我们知道,这个CallAdapter
类的adapt()
方法返回了一个ExecutorCallbackCall
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 static final class ExecutorCallbackCall <T > implements Call <T > { final Executor callbackExecutor; final Call<T> delegate; ExecutorCallbackCall(Executor callbackExecutor, Call<T> delegate) { this .callbackExecutor = callbackExecutor; this .delegate = delegate; } @Override public void enqueue (final Callback<T> callback) { checkNotNull(callback, "callback == null" ); delegate.enqueue(new Callback<T>() { @Override public void onResponse (Call<T> call, final Response<T> response) { callbackExecutor.execute(new Runnable() { @Override public void run () { if (delegate.isCanceled()) { callback.onFailure(ExecutorCallbackCall.this , new IOException("Canceled" )); } else { callback.onResponse(ExecutorCallbackCall.this , response); } } }); } @Override public void onFailure (Call<T> call, final Throwable t) { callbackExecutor.execute(new Runnable() { @Override public void run () { callback.onFailure(ExecutorCallbackCall.this , t); } }); } }); } @Override public Response<T> execute () throws IOException { return delegate.execute(); } }
我们可以看见这个默认的ExecutorCallbackCall
仅仅是把结果回调CallBack放到了对应的CallbackExecutor
去执行,并没有对结果进行任何加工。
设计模式 一般客户端向服务器请求API,总共分三步:
build request(API参数配置)
executor(这里可以有很多变体,比如有无队列,进出顺序,线程管理)
parse callback(解析数据,返回T给上层)
如今的retrofit也是换汤不换药的。也是这三步:
通过定义interface和使用注解来配置API参数
CallAdapter
(你可以把它理解成executor)
Converter
(解析数据并转换成T)
Retrofit采用了外观模式 统一调用创建网络请求接口实例和网络请求参数配置的方法,具体细节是:
动态创建网络请求接口的实例(代理模式 - 动态代理)
创建 serviceMethod
对象(建造者模式 & 单例模式(缓存机制))
对 serviceMethod
对象进行网络请求参数配置:通过解析网络请求接口方法的参数、返回值和注解类型,从Retrofit对象中获取对应的网络请求的url地址、网络请求执行器、网络请求适配器 & 数据转换器。(策略模式)
对 serviceMethod
对象加入线程切换的操作,便于接收数据后通过Handler从子线程切换到主线程从而对返回数据结果进行处理(装饰模式)
最终创建并返回一个OkHttpCall
类型的网络请求对象
参考资料