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

本文详细介绍了Retrofit的基本使用流程,强调了其简洁背后依赖的九大设计模式(如建造者模式、工厂方法模式等),以及对OkHttp源码的理解。作者引导读者从构建过程、接口实例创建和请求执行等方面深入Retrofit源码,感受其设计之美。
摘要由CSDN通过智能技术生成

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;

}

}

call = rawCall;

if (call == null) {

try {

// 创建一个OkHttp的Request对象请求

call = rawCall = createRawCall();

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则近万的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

img

img

img

img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(资料价值较高,非无偿)

结语

看到这篇文章的人不知道有多少是和我一样的Android程序员。

35岁,这是我们这个行业普遍的失业高发阶段,这种情况下如果还不提升自己的技能,进阶发展,我想,很可能就是本行业的职业生涯的终点了。

我们要有危机意识,切莫等到一切都成定局时才开始追悔莫及。只要有规划的,有系统地学习,进阶提升自己并不难,给自己多充一点电,你才能走的更远。

千里之行始于足下。这是上小学时,那种一元钱一个的日记本上每一页下面都印刷有的一句话,当时只觉得这句话很短,后来渐渐长大才慢慢明白这句话的真正的含义。

有了学习的想法就赶快行动起来吧,不要被其他的事情牵绊住了前行的脚步。不要等到裁员时才开始担忧,不要等到面试前一晚才开始紧张,不要等到35岁甚至更晚才开始想起来要学习要进阶。

给大家一份系统的Android学习进阶资料,希望这份资料可以给大家提供帮助。

《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》,点击传送门即可获取!

份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。**

[外链图片转存中…(img-QJLZrzGA-1711591184094)]

[外链图片转存中…(img-rt0Gz84n-1711591184095)]

[外链图片转存中…(img-HOyAPCMI-1711591184095)]

[外链图片转存中…(img-ptzDi6S1-1711591184095)]

[外链图片转存中…(img-1L5WeViJ-1711591184096)]

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(资料价值较高,非无偿)

结语

看到这篇文章的人不知道有多少是和我一样的Android程序员。

35岁,这是我们这个行业普遍的失业高发阶段,这种情况下如果还不提升自己的技能,进阶发展,我想,很可能就是本行业的职业生涯的终点了。

我们要有危机意识,切莫等到一切都成定局时才开始追悔莫及。只要有规划的,有系统地学习,进阶提升自己并不难,给自己多充一点电,你才能走的更远。

千里之行始于足下。这是上小学时,那种一元钱一个的日记本上每一页下面都印刷有的一句话,当时只觉得这句话很短,后来渐渐长大才慢慢明白这句话的真正的含义。

有了学习的想法就赶快行动起来吧,不要被其他的事情牵绊住了前行的脚步。不要等到裁员时才开始担忧,不要等到面试前一晚才开始紧张,不要等到35岁甚至更晚才开始想起来要学习要进阶。

给大家一份系统的Android学习进阶资料,希望这份资料可以给大家提供帮助。
[外链图片转存中…(img-N38S9LWs-1711591184096)]

《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》,点击传送门即可获取!
  • 5
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值