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

本文详细介绍了Retrofit的构建过程,包括设置默认平台、配置callAdapterFactories、callbackExecutor、baseUrl以及添加GsonConverterFactory。重点展示了如何通过Builder逐步构建网络请求接口实例,并执行请求,涉及Android平台特定的适配策略和装饰者模式的应用。
摘要由CSDN通过智能技术生成

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

Android进阶资料

以下的资料是近年来,我和一些朋友面试收集整理了很多大厂的面试真题和资料,还有来自如阿里、小米、爱奇艺等一线大厂的大牛整理的架构进阶资料。希望可以帮助到大家。

Android进阶核心笔记

百万年薪必刷面试题

最全Android进阶学习视频

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化学习资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

T>) converter;

}

}

复制代码

最终,执行HttpServiceMethod的invoke方法

@Override ReturnT invoke(Object[] args) {

return callAdapter.adapt(

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

}

复制代码

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

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

1、service.listRepos()

Android进阶资料

以下的资料是近年来,我和一些朋友面试收集整理了很多大厂的面试真题和资料,还有来自如阿里、小米、爱奇艺等一线大厂的大牛整理的架构进阶资料。希望可以帮助到大家。

Android进阶核心笔记

[外链图片转存中…(img-mG0pnavo-1714044525518)]

百万年薪必刷面试题

[外链图片转存中…(img-0JwpNQtS-1714044525518)]

最全Android进阶学习视频

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化学习资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

  • 13
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值