前面的文章我们分析了 OkHttp 的核心源码,而 Retrofit 与 OkHttp 的结合使用,也是目前主流的方式,这篇文章主要分析下目前 Android 最优秀的网络封装框架 Retrofit。
在分析 Retrofit 源码之前,先看下 Retrofit 的简单使用。
基本使用
一般情况,Retrofit 的使用流程按照以下三步:
1、将 HTTP API 定义成接口形式
1 2 3 4 public interface GitHubService { @GET("users/{user}/repos") Call<List<Repo>> listRepos(@Path("user") String user); }
2、构建 Retrofit 实例,生成 GitHubService 接口的实现。
1 2 3 4 5 6 Retrofit retrofit = new Retrofit.Builder() .baseUrl("https://api.github.com/" ) .build(); GitHubService service = retrofit.create(GitHubService.class);
3、发起网络请求,可以做同步或异步请求。
1 2 3 Call<List<Repo>> repos = service.listRepos("octocat" ); call.execute() 或者 call.enqueue()
这里,Retrofit 用注解标识不同的网络请求类型,极大的简化了 OkHttp 的使用方式。
这篇文章主要关注的几个问题:
Retrofit 创建过程
1 2 3 Retrofit retrofit = new Retrofit.Builder() .baseUrl("https://api.github.com/" ) .build();
这里可以看出,Retrofit 实例是使用建造者模式通过 Builder 类进行创建。
建造者模式简言之:将一个复杂对象的构建与表示分离,使得用户在不知道对象的创建细节情况下可以直接创建复杂的对象。
Retrofit
Retrofit 包含 7 个成员变量:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 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 构造函数,除了 serviceMethodCache, 其他成员变量都在这里进行赋值。
1 2 3 4 5 6 7 8 9 10 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.Builder
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 public static final class Builder { private final Platform platform; private @Nullable okhttp3.Call.Factory callFactory; private @Nullable 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()); } ... }
这里主要关注 Platform,在 Builder 构造函数中调用了 Platform.get()
,然后赋值给自己的 platform 变量,我们来看看 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 25 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(); } }
Platform.get()
方法会调用 findPlatform()
方法,这里主要是判断是 Android 平台还是 Java 平台,如果是 Android 平台会返回一个 Android 对象。
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 static class Android extends Platform { @IgnoreJRERequirement @Override boolean isDefaultMethod (Method method) { if (Build.VERSION.SDK_INT < 24 ) { return false ; } return method.isDefault(); } @Override public Executor defaultCallbackExecutor () { return new MainThreadExecutor(); } @Override List<? extends CallAdapter.Factory> defaultCallAdapterFactories( @Nullable Executor callbackExecutor) { if (callbackExecutor == null ) throw new AssertionError(); DefaultCallAdapterFactory executorFactory = new DefaultCallAdapterFactory(callbackExecutor); return Build.VERSION.SDK_INT >= 24 ? asList(CompletableFutureCallAdapterFactory.INSTANCE, executorFactory) : singletonList(executorFactory); } @Override int defaultCallAdapterFactoriesSize () { return Build.VERSION.SDK_INT >= 24 ? 2 : 1 ; } @Override List<? extends Converter.Factory> defaultConverterFactories() { return Build.VERSION.SDK_INT >= 24 ? singletonList(OptionalConverterFactory.INSTANCE) : Collections.<Converter.Factory>emptyList(); } @Override int defaultConverterFactoriesSize () { return Build.VERSION.SDK_INT >= 24 ? 1 : 0 ; } static class MainThreadExecutor implements Executor { private final Handler handler = new Handler(Looper.getMainLooper()); @Override public void execute (Runnable r) { handler.post(r); } } }
关注三个重要的方法:
defaultCallbackExecutor
: 返回默认的 Executor 对象,正是 Retrofit 的成员变量回调执行器,它的内部采用 Handler 负责子线程到主线程的切换工作。
defaultCallAdapterFactories
:返回的是默认的 CallAdpter.Factory 的集合,也就是 Retrofit 的成员变量网络请求适配器工厂集合,如果是 Android 7.0 以上或者 Java 8,使用并发包中的 CompletableFuture 保证了回调的同步。
defaultConverterFactories
:返回的是默认的 Converter.Factory 的集合,也就是 Retrofit 的成员变量数据转换器工厂集合。
build 过程
接着看一下 Builder.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 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.addAll(platform.defaultCallAdapterFactories(callbackExecutor)); List<Converter.Factory> converterFactories = new ArrayList<>( 1 + this .converterFactories.size() + platform.defaultConverterFactoriesSize()); converterFactories.add(new BuiltInConverters()); converterFactories.addAll(this .converterFactories); converterFactories.addAll(platform.defaultConverterFactories()); return new Retrofit(callFactory, baseUrl, unmodifiableList(converterFactories), unmodifiableList(callAdapterFactories), callbackExecutor, validateEagerly); }
至此,Retrofit 的创建流程就完成了,它的成员变量的值如下:
serviceMethodService:暂时为空的 ConcurrentHashMap
callFactory:默认OkHttpClient 对象
baseUrl:根据配置的 baseUrl,构建 HttpUrl 对象
callAdapterFactories:配置的和默认的网络请求适配器工厂集合
converterFactories:配置的和默认的数据转换器工厂集合
callbackExecutor:MainThreadExecutor 对象
validateEagerly:默认 false
创建网络请求接口实例
接着来看 GitHubService 实例是如何创建的。
1 GitHubService service = retrofit.create(GitHubService.class);
Service 创建
retrofit.create()
使用了外观模式和代理模式创建了网络请求接口实例。
外观模式:定义一个统一接口,外部与通过该统一的接口对子系统里的其他接口进行访问。
代理模式:通过访问代理对象的方式来间接访问目标对象。
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 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(); private final Object[] emptyArgs = new Object[0 ]; @Override public @Nullable Object invoke (Object proxy, Method method, @Nullable 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); } return loadServiceMethod(method).invoke(args != null ? args : emptyArgs); } }); }
retrofit.create()
返回的是代理对象 Proxy,并转换为 T 类型,即 GitHubService。这里利用了动态代理技术,自动生成 Service 接口的实现类,将 Service 接口方法中的参数交给 InvocationHandler 处理。
对于 Object 类本身独有以及对应平台本身存在的方法,就直接调用,否则通过 loadServiceMethod()
对 Service 接口中对应的 method 进行解析处理,之后对其调用 invoke()
方法。
可以看出,Retrofit 不是在创建 Service 接口实例时就立即对所有接口中的方法进行注解解析,而是采用了在方法被调用时才进行注解的解析,也就是懒加载。
validateEagerly 的作用
我们看看 validateEagerly 这个变量,看看它控制着什么。validateEagerly 为 true 会进入 eagerlyValidateMethods()
方法。
1 2 3 4 5 6 7 8 private void eagerlyValidateMethods (Class<?> service) { Platform platform = Platform.get(); for (Method method : service.getDeclaredMethods()) { if (!platform.isDefaultMethod(method) && !Modifier.isStatic(method.getModifiers())) { loadServiceMethod(method); } } }
这里循环取出接口中的 Method,调用 loadServiceMethod()
, loadServiceMethod()
先从 serviceMethodCache 获取 Method 对应的 ServiceMethod,如果有直接返回,否则对 Method 进行解析得到一个 ServiceMethod 对象,存入缓存中。
所以 validateEagerly 变量是用于判断是否需要提前验证解析的,默认为 false,如果在 Retrofit 创建时设置为 true,会对 Service 接口中所有方法进行提前解析处理。
ServiceMethod 创建过程
loadServiceMethod()
方法的具体实现如下,这里采用了 Double Check 的方式尝试从 serviceMethodCache 中获取 ServiceMethod 对象,如果获取不到则通过 ServiceMethod.parseAnnotations()
方法对该 method 的注解进行处理并将得到的 ServiceMethod 对象加入缓存。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 ServiceMethod<?> loadServiceMethod(Method method) { ServiceMethod<?> result = serviceMethodCache.get(method); if (result != null ) return result; synchronized (serviceMethodCache) { result = serviceMethodCache.get(method); if (result == null ) { result = ServiceMethod.parseAnnotations(this , method); serviceMethodCache.put(method, result); } } return result; }
我们详细看一下 ServiceMethod 创建过程。 ServiceMethod.parseAnnotations()
方法具体实现:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 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." ); } return HttpServiceMethod.parseAnnotations(retrofit, method, requestFactory); }
1、通过 RequestFactory 解析注解配置
通过工厂模式和建造者模式创建 RequestFactory,解析封装注解配置。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 static RequestFactory parseAnnotations (Retrofit retrofit, Method method) { return new Builder(retrofit, method).build(); } Builder(Retrofit retrofit, Method method) { this .retrofit = retrofit; this .method = method; this .methodAnnotations = method.getAnnotations(); this .parameterTypes = method.getGenericParameterTypes(); this .parameterAnnotationsArray = method.getParameterAnnotations(); }
2、ServiceMethod 的创建
ServiceMethod 的创建在 HttpServiceMethod 的 parseAnnotations()
方法中。
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 static <ResponseT, ReturnT> HttpServiceMethod<ResponseT, ReturnT> parseAnnotations ( Retrofit retrofit, Method method, RequestFactory requestFactory) { boolean isKotlinSuspendFunction = requestFactory.isKotlinSuspendFunction; boolean continuationWantsResponse = false ; boolean continuationBodyNullable = false ; Annotation[] annotations = method.getAnnotations(); Type adapterType; if (isKotlinSuspendFunction) { Type[] parameterTypes = method.getGenericParameterTypes(); Type responseType = Utils.getParameterLowerBound(0 , (ParameterizedType) parameterTypes[parameterTypes.length - 1 ]); if (getRawType(responseType) == Response.class && responseType instanceof ParameterizedType) { responseType = Utils.getParameterUpperBound(0 , (ParameterizedType) responseType); continuationWantsResponse = true ; } else { } adapterType = new Utils.ParameterizedTypeImpl(null , Call.class, responseType); annotations = SkipCallbackExecutorImpl.ensurePresent(annotations); } else { adapterType = method.getGenericReturnType(); } CallAdapter<ResponseT, ReturnT> callAdapter = createCallAdapter(retrofit, method, adapterType, annotations); Type responseType = callAdapter.responseType(); if (responseType == okhttp3.Response.class) { throw methodError(method, "'" + getRawType(responseType).getName() + "' is not a valid response body type. Did you mean ResponseBody?" ); } if (responseType == Response.class) { throw methodError(method, "Response must include generic type (e.g., Response<String>)" ); } if (requestFactory.httpMethod.equals("HEAD" ) && !Void.class.equals(responseType)) { throw methodError(method, "HEAD method must use Void as response type." ); } Converter<ResponseBody, ResponseT> responseConverter = createResponseConverter(retrofit, method, responseType); okhttp3.Call.Factory callFactory = retrofit.callFactory; if (!isKotlinSuspendFunction) { return new CallAdapted<>(requestFactory, callFactory, responseConverter, callAdapter); } else if (continuationWantsResponse) { return (HttpServiceMethod<ResponseT, ReturnT>) new SuspendForResponse<>(requestFactory, callFactory, responseConverter, (CallAdapter<ResponseT, Call<ResponseT>>) callAdapter); } else { return (HttpServiceMethod<ResponseT, ReturnT>) new SuspendForBody<>(requestFactory, callFactory, responseConverter, (CallAdapter<ResponseT, Call<ResponseT>>) callAdapter, continuationBodyNullable); } }
HttpServiceMethod.parseAnnotations()
的主要作用就是获取 CallAdapter 以及 Converter 对象,并构建对应 HttpServiceMethod
。
CallAdapter :根据网络接口方法的返回值类型来选择具体要用哪种 CallAdapterFactory,然后获取具体的 CallAdapter。
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 private static <ResponseT, ReturnT> CallAdapter<ResponseT, ReturnT> createCallAdapter ( Retrofit retrofit, Method method, Type returnType, Annotation[] annotations) { try { return (CallAdapter<ResponseT, ReturnT>) retrofit.callAdapter(returnType, annotations); } catch (RuntimeException e) { throw methodError(method, e, "Unable to create call adapter for %s" , returnType); } } public CallAdapter<?, ?> callAdapter(Type returnType, Annotation[] annotations) { return nextCallAdapter(null , returnType, annotations); } public CallAdapter<?, ?> nextCallAdapter(@Nullable CallAdapter.Factory skipPast, Type returnType, Annotation[] annotations) { 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; } } ... }
获取 Converter:根据网络请求接口方法的返回值和注解类型从 Retrofit 对象中获取对应的数据转换器,和创建 CallAdapter 基本一致,遍历 Converter.Factory 集合并寻找具体的 Converter。
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 private static <ResponseT> Converter<ResponseBody, ResponseT> createResponseConverter ( Retrofit retrofit, Method method, Type responseType) { Annotation[] annotations = method.getAnnotations(); try { return retrofit.responseBodyConverter(responseType, annotations); } catch (RuntimeException e) { throw methodError(method, e, "Unable to create converter for %s" , responseType); } } 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) { 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; } } ... }
构建 HttpServiceMethod:根据是否是 kotlin suspend 方法分别返回不同类型的 HttpServiceMethod。如果不是 suspend 方法的话则直接创建并返回一个 CallAdapted 对象,否则根据 suspend 方法需要的是 Response 还是具体的类型,分别返回 SuspendForResponse 和 SuspendForBody 对象。
ServiceMethod.invoke()
ServiceMethod 是一个抽象类,invoke()
是一个抽象方法,具体实现在子类中。
1 2 3 abstract class ServiceMethod <T > { abstract @Nullable T invoke (Object[] args) ; }
它的子类是 HttpServiceMethod,HttpServiceMethod 的 invoke()
方法中,首先构造一个 OkHttpCall,然后通过 adapt()
方法实现对 Call 的转换。
1 2 3 4 5 6 7 8 9 abstract class HttpServiceMethod <ResponseT , ReturnT > extends ServiceMethod <ReturnT > { @Override final @Nullable ReturnT invoke (Object[] args) { Call<ResponseT> call = new OkHttpCall<>(requestFactory, args, callFactory, responseConverter); return adapt(call, args); } protected abstract @Nullable ReturnT adapt (Call<ResponseT> call, Object[] args) ; }
adapt()
是一个 抽象方法,所以具体实现在 HttpServiceMethod 的子类中。
HttpServiceMethod 有三个子类,非协程的情况是 CallAdapted,另外两个子类则是在使用协程的情况下为了配合协程的 SuspendForResponse 以及 SuspendForBody 类。
CallAdapted:通过传递进来的 CallAdapter 对 Call 进行转换。
SuspendForResponse:首先根据传递进来的 Call 构造了一个参数为 Response 的 Continuation 对象然后通过 Kotlin 实现的 awaitResponse()
方法将 call 的 enqueue
异步回调过程封装成 一个 suspend 的函数。
SuspendForBody:SuspendForBody 则是根据传递进来的 Call 构造了一个 Continuation 对象然后通过 Kotlin 实现的 await()
或 awaitNullable()
方法将 call 的 enqueue
异步回调过程封装为了一个 suspend 的函数。
发起网络请求
创建 Call
1 Call<List<Repo>> repos = service.listRepos("octocat" );
从前面的分析了解到,Service 对象是动态代理对象,当调用 listRepos()
方法时会调用到 InvocationHandler的 invoke()
方法,得到最终的 Call 对象。
如果没有传入 CallAdapter 的话,默认情况返回的 Call 是 OkHttpCall 对象,它实现了 Call 接口。
同步请求
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 @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()); }
很简单,主要就是创建 OkHttp 的 Call 对象,调用 Call 的 execute
方法,对 Response 进行解析返回。
异步请求
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 @Override public void enqueue (final Callback<T> callback) { checkNotNull(callback, "callback == null" ); okhttp3.Call call; Throwable failure; synchronized (this ) { if (executed) throw new IllegalStateException("Already executed." ); executed = true ; call = rawCall; failure = creationFailure; if (call == null && failure == null ) { try { call = rawCall = createRawCall(); } catch (Throwable t) { throwIfFatal(t); failure = creationFailure = t; } } } if (failure != null ) { callback.onFailure(this , failure); return ; } if (canceled) { call.cancel(); } call.enqueue(new okhttp3.Callback() { @Override public void onResponse (okhttp3.Call call, okhttp3.Response rawResponse) { Response<T> response; try { response = parseResponse(rawResponse); } catch (Throwable e) { throwIfFatal(e); callFailure(e); return ; } try { callback.onResponse(OkHttpCall.this , response); } catch (Throwable t) { throwIfFatal(t); t.printStackTrace(); } } @Override public void onFailure (okhttp3.Call call, IOException e) { callFailure(e); } private void callFailure (Throwable e) { try { callback.onFailure(OkHttpCall.this , e); } catch (Throwable t) { throwIfFatal(t); t.printStackTrace(); } } }); }
也很简单,主要就是创建 OkHttp 的 Call 对象,调用 Call 的 enqueue
方法,解析返回结果,执行回调。
总结
至此,Retrofit 的源码基本上就看完了,虽然还有很多细节没有提及,但 Retrofit 的整体流程很清晰了。
Retrofit 本质上是一个 RESTful 的 Http 网络请求框架的封装,通过大量的设计模式封装了 OkHttp,使得更加简单易用。它内部主要是用动态代理的方式,动态将网络请求接口的注解解析成 HTTP 请求,最后执行请求的过程。
建议将 Retrofit 的源码下载下来,使用 IDEA 可以直接打开阅读。我这边已经将源码下载下来,进行了注释说明,有需要的可以直接从 Android open framework analysis 查看。
参考
1、Android开源框架源码鉴赏:Retrofit
2、Android:手把手带你 深入读懂 Retrofit 2.0 源码
3、带你一步步剖析Retrofit 源码解析:一款基于 OkHttp 实现的网络请求框架