Android主流三方库源码分析:Retrofit

// 3.生成并执行请求过程

Call<List> repos = service.listRepos(“octocat”);

repos.execute() or repos.enqueue()

复制代码

Retrofit的基本使用流程很简洁,但是简洁并不代表简单,Retrofit为了实现这种简洁的使用流程,内部使用了优秀的架构设计和大量的设计模式,在我分析过Retrofit最新版的源码和大量优秀的Retrofit源码分析文章后,我发现,要想真正理解Retrofit内部的核心源码流程和设计思想,首先,需要对这九大设计模式有一定的了解,如下:

1.Retrofit构建过程

建造者模式、工厂方法模式

2.创建网络请求接口实例过程

外观模式、代理模式、单例模式、策略模式、装饰模式(建造者模式)

3.生成并执行请求过程

适配器模式(代理模式、装饰模式)

复制代码

其次,需要对OKHttp源码有一定的了解,如果不了解的可以看看这篇Android主流三方库源码分析(一、深入理解OKHttp源码)。最后,让我们按以上流程去深入Retrofit源码内部,领悟它带给我们的设计之美

二、Retrofit构建过程

1、Retrofit核心对象解析

首先Retrofit中有一个全局变量非常关键,在V2.5之前的版本,使用的是LinkedHashMap(),它是一个网络请求配置对象,是由网络请求接口中方法注解进行解析后得到的。

public final class Retrofit {

// 网络请求配置对象,存储网络请求相关的配置,如网络请求的方法、数据转换器、网络请求适配器、网络请求工厂、基地址等

private final Map<Method, ServiceMethod<?>> serviceMethodCache = new ConcurrentHashMap<>();

复制代码

Retrofit使用了建造者模式通过内部类Builder类建立一个Retrofit实例,如下:

public static final class Builder {

// 平台类型对象(Platform -> Android)

private final Platform platform;

// 网络请求工厂,默认使用OkHttpCall(工厂方法模式)

private @Nullable okhttp3.Call.Factory callFactory;

// 网络请求的url地址

private @Nullable HttpUrl baseUrl;

// 数据转换器工厂的集合

private final List<Converter.Factory> converterFactories = new ArrayList<>();

// 网络请求适配器工厂的集合,默认是ExecutorCallAdapterFactory

private final List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>();

// 回调方法执行器,在 Android 上默认是封装了 handler 的 MainThreadExecutor, 默认作用是:切换线程(子线程 -> 主线程)

private @Nullable Executor callbackExecutor;

// 一个开关,为true则会缓存创建的ServiceMethod

private boolean validateEagerly;

复制代码

2、Builder内部构造

下面看看Builder内部构造做了什么。

public static final class Builder {

Builder(Platform platform) {

this.platform = platform;

}

public Builder() {

this(Platform.get());

}

}

class Platform {

private static final Platform PLATFORM = findPlatform();

static Platform get() {

return PLATFORM;

}

private static Platform findPlatform() {

try {

// 使用JVM加载类的方式判断是否是Android平台

Class.forName(“android.os.Build”);

if (Build.VERSION.SDK_INT != 0) {

return new Android();

}

} catch (ClassNotFoundException ignored) {

}

try {

// 同时支持Java平台

Class.forName(“java.util.Optional”);

return new Java8();

} catch (ClassNotFoundException ignored) {

}

return new Platform();

}

static class Android extends Platform {

@Override public Executor defaultCallbackExecutor() {

//切换线程(子线程 -> 主线程)

return new MainThreadExecutor();

}

// 创建默认的网络请求适配器工厂,如果是Android7.0或Java8上,则使

// 用了并发包中的CompletableFuture保证了回调的同步

// 在Retrofit中提供了四种CallAdapterFactory(策略模式):

// ExecutorCallAdapterFactory(默认)、GuavaCallAdapterFactory、

// va8CallAdapterFactory、RxJavaCallAdapterFactory

@Override List<? extends CallAdapter.Factory> defaultCallAdapterFactories(

@Nullable Executor callbackExecutor) {

if (callbackExecutor == null) throw new AssertionError();

ExecutorCallAdapterFactory executorFactory = new ExecutorCallAdapterFactory(callbackExecutor);

return Build.VERSION.SDK_INT >= 24

? asList(CompletableFutureCallAdapterFactory.INSTANCE, executorFactory)
singletonList(executorFactory);

}

@Override List<? extends Converter.Factory> defaultConverterFactories() {

return Build.VERSION.SDK_INT >= 24

? singletonList(OptionalConverterFactory.INSTANCE)
Collections.<Converter.Factory>emptyList();

}

static class MainThreadExecutor implements Executor {

// 获取Android 主线程的Handler

private final Handler handler = new Handler(Looper.getMainLooper());

@Override public void execute(Runnable r) {

// 在UI线程对网络请求返回数据处理

handler.post®;

}

}

}

复制代码

可以看到,在Builder内部构造时设置了默认Platform、callAdapterFactories和callbackExecutor。

3、添加baseUrl

很简单,就是将String类型的url转换为OkHttp的HttpUrl过程如下:

/**

  • Set the API base URL.

  • @see #baseUrl(HttpUrl)

*/

public Builder baseUrl(String baseUrl) {

checkNotNull(baseUrl, “baseUrl == null”);

return baseUrl(HttpUrl.get(baseUrl));

}

public Builder baseUrl(HttpUrl baseUrl) {

checkNotNull(baseUrl, “baseUrl == null”);

List pathSegments = baseUrl.pathSegments();

if (!“”.equals(pathSegments.get(pathSegments.size() - 1))) {

throw new IllegalArgumentException("baseUrl must end in /: " + baseUrl);

}

this.baseUrl = baseUrl;

return this;

}

复制代码

4、添加GsonConverterFactory

首先,看到GsonConverterFactory.creat()的源码。

public final class GsonConverterFactory extends Converter.Factory {

public static GsonConverterFactory create() {

return create(new Gson());

}

public static GsonConverterFactory create(Gson gson) {

if (gson == null) throw new NullPointerException(“gson == null”);

return new GsonConverterFactory(gson);

}

private final Gson gson;

// 创建了一个含有Gson对象实例的GsonConverterFactory

private GsonConverterFactory(Gson gson) {

this.gson = gson;

}

复制代码

然后,看看addConverterFactory()方法内部。

public Builder addConverterFactory(Converter.Factory factory) {

converterFactories.add(checkNotNull(factory, “factory null”));

return this;

}

复制代码

可知,这一步是将一个含有Gson对象实例的GsonConverterFactory放入到了数据转换器工厂converterFactories里。

5、build过程

public Retrofit build() {

if (baseUrl == null) {

throw new IllegalStateException(“Base URL required.”);

}

okhttp3.Call.Factory callFactory = this.callFactory;

if (callFactory == null) {

// 默认使用okhttp

callFactory = new OkHttpClient();

}

Executor callbackExecutor = this.callbackExecutor;

if (callbackExecutor == null) {

// Android默认的callbackExecutor

callbackExecutor = platform.defaultCallbackExecutor();

}

// Make a defensive copy of the adapters and add the defaultCall adapter.

List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>(this.callAdapterFactories);

// 添加默认适配器工厂在集合尾部

callAdapterFactories.addAll(platform.defaultCallAdapterFactorisca llbackExecutor));

// Make a defensive copy of the converters.

List<Converter.Factory> converterFactories = new ArrayList<>(

1 + this.converterFactories.size() + platform.defaultConverterFactoriesSize());

// Add the built-in converter factory first. This prevents overriding its behavior but also

// ensures correct behavior when using converters thatconsumeall types.

converterFactories.add(new BuiltInConverters());

converterFactories.addAll(this.converterFactories);

converterFactories.addAll(platform.defaultConverterFactories();

return new Retrofit(callFactory, baseUrl, unmodifiableList(converterFactories),

unmodifiableList(callAdapterFactories), callbackExecutor, validateEagerly);

}

复制代码

可以看到,最终我们在Builder类中看到的6大核心对象都已经配置到Retrofit对象中了。

三、创建网络请求接口实例过程

retrofit.create()使用了外观模式和代理模式创建了网络请求的接口实例,我们分析下create方法。

public T create(final Class service) {

Utils.validateServiceInterface(service);

if (validateEagerly) {

// 判断是否需要提前缓存ServiceMethod对象

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 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);

}

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

}

});

}

private void eagerlyValidateMethods(Class<?> service) {

Platform platform = Platform.get();

for (Method method : service.getDeclaredMethods()) {

if (!platform.isDefaultMethod(method)) {

loadServiceMethod(method);

}

}

}

复制代码

继续看看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);

// 可以看到,最终加入到ConcurrentHashMap缓存中

serviceMethodCache.put(method, result);

}

}

return result;

}

abstract class ServiceMethod {

static ServiceMethod parseAnnotations(Retrofit retrofit, Method method) {

// 通过RequestFactory解析注解配置(工厂模式、内部使用了建造者模式)

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);

}

复制代码

以下为请求构造核心流程

根据RequestFactory#Builder构造方法和parseAnnotations方法的源码,可知的它的作用就是用来解析注解配置的。

Builder(Retrofit retrofit, Method method) {

this.retrofit = retrofit;

this.method = method;

// 获取网络请求接口方法里的注释

this.methodAnnotations = method.getAnnotations();

// 获取网络请求接口方法里的参数类型

this.parameterTypes = method.getGenericParameterTypes();

// 获取网络请求接口方法里的注解内容

this.parameterAnnotationsArray = method.getParameterAnnotations();

}

复制代码

接着看HttpServiceMethod.parseAnnotations()的内部流程。

static <ResponseT, ReturnT> HttpServiceMethod<ResponseT, ReturnT> parseAnnotations(

Retrofit retrofit, Method method, RequestFactory requestFactory) {

//1.根据网络请求接口方法的返回值和注解类型,

// 从Retrofit对象中获取对应的网络请求适配器

CallAdapter<ResponseT, ReturnT> callAdapter = createCallAdapter(retrofit,method);

// 得到响应类型

Type responseType = callAdapter.responseType();

//2.根据网络请求接口方法的返回值和注解类型从Retrofit对象中获取对应的数据转换器

Converter<ResponseBody, ResponseT>responseConverter =

createResponseConverter(retrofit,method, responseType);

okhttp3.Call.Factory callFactory = retrofit.callFactory;

return newHttpServiceMethod<>(requestFactory, callFactory, callAdapter,responseConverter);

}

复制代码

1.createCallAdapter(retrofit, method)

private static <ResponseT, ReturnT> CallAdapter<ResponseT, ReturnT> createCallAdapter(

Retrofit retrofit, Method method) {

// 获取网络请求接口里方法的返回值类型

Type returnType = method.getGenericReturnType();

// 获取网络请求接口接口里的注解

Annotation[] annotations = method.getAnnotations();

try {

//noinspection unchecked

return (CallAdapter<ResponseT, ReturnT>) retrofit.callAdapter(returnType, annotations);

} catch (RuntimeException e) { // Wide exception range because factories are user code.

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;

// 遍历 CallAdapter.Factory 集合寻找合适的工厂

for (int i = start, count = callAdapterFactories.size(); i <count; i++) {

CallAdapter<?, ?> adapter = callAdapterFactories.get(i).get(returnType, annotations, this);

if (adapter != null) {

return adapter;

}

}

}

复制代码

2.createResponseConverter(Retrofit retrofit, Method method, Type responseType)

private static Converter<ResponseBody, ResponseT> createResponseConverter(

Retrofit retrofit, Method method, Type responseType) {

Annotation[] annotations = method.getAnnotations();

try {

return retrofit.responseBodyConverter(responseType,annotations);

} catch (RuntimeException e) { // Wide exception range because factories are user code.

throw methodError(method, e, “Unable to create converter for%s”, responseType);

}

}

public Converter<ResponseBody, T> responseBodyConverter(Type type, Annotation[] annotations) {

return nextResponseBodyConverter(null, type, annotations);

}

public Converter<ResponseBody, T> nextResponseBodyConverter(

@Nullable Converter.Factory skipPast, Type type, Annotation[] annotations) {

int start = converterFactories.indexOf(skipPast) + 1;

// 遍历 Converter.Factory 集合并寻找合适的工厂, 这里是GsonResponseBodyConverter

for (int i = start, count = converterFactories.size(); i < count; i++) {

Converter<ResponseBody, ?> converter =

converterFactories.get(i).responseBodyConverter(type, annotations, this);

if (converter != null) {

//noinspection unchecked

return (Converter<ResponseBody, T>) converter;

}

}

复制代码

最终,执行HttpServiceMethod的invoke方法

@Override ReturnT invoke(Object[] args) {

return callAdapter.adapt(

new OkHttpCall<>(requestFactory, args, callFactory, responseConverter));

}

复制代码

最终在adapt中创建了一个ExecutorCallbackCall对象,它是一个装饰者,而在它内部真正去执行网络请求的还是OkHttpCall。

四、创建网络请求接口类实例并执行请求过程

1、service.listRepos()

1、Call<List> repos = service.listRepos(“octocat”);

复制代码

service对象是动态代理对象Proxy.newProxyInstance(),当调用getCall()时会被 它拦截,然后调用自身的InvocationHandler#invoke(),得到最终的Call对象。

2、同步执行流程 repos.execute()

@Override public Response 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;

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值