一线互联网企业老Android开发谈:Retrofit的源码你真的看懂这些了吗?

IpService ipService = retrofit.create(IpService.class);

接下来看Retrofit的create方法做了什么,代码如下所示。

public T create(final Class 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 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);

}

ServiceMethod serviceMethod = loadServiceMethod(method);//1

OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args);

return serviceMethod.callAdapter.adapt(okHttpCall);

}

});

}

可以看到create方法返回了一个Proxy.newProxyInstance动态代理对象,当我们调用IpService的getIpMsg方法最终会调用InvocationHandler的invoke 方法,它有3个参数,第一个是代理对象,第二个是调用的方法,第三个是方法的参数。注释1处的loadServiceMethod(method)中的method就是我们定义的getIpMsg方法。接下来查看loadServiceMethod方法里做了什么:

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

ServiceMethod loadServiceMethod(Method method) {

ServiceMethod 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,如果没有就创建一个,并加入serviceMethodCache缓存起来。接下来看ServiceMethod是如何构建的,代码如下所示。

public ServiceMethod build() {

callAdapter = createCallAdapter();//1

responseType = callAdapter.responseType();//2

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();//3

for (Annotation annotation : methodAnnotations) {

parseMethodAnnotation(annotation);//4

}

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];//5

if (parameterAnnotations == null) {

throw parameterError(p, “No Retrofit annotation found.”);

}

parameterHandlers[p] = parseParameter(p, parameterType, parameterAnnotations);

}

return new ServiceMethod<>(this);

}

注释1处调用了createCallAdapter方法,它最终会得到我们在构建Retrofit调用build方法时adapterFactories添加的对象的get方法,Retrofit的build方法部分代码:

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

adapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor));

adapterFactories列表默认会添加defaultCallAdapterFactory,defaultCallAdapterFactory指的是ExecutorCallAdapterFactory,ExecutorCallAdapterFactory的get方法如下所示。

public CallAdapter<Call<?>> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {

if (getRawType(returnType) != Call.class) {

return null;

}

final Type responseType = Utils.getCallResponseType(returnType);

return new CallAdapter<Call<?>>() {

@Override public Type responseType() {

return responseType;

}

@Override public Call adapt(Call call) {

return new ExecutorCallbackCall<>(callbackExecutor, call);

}

};

}

get方法会得到CallAdapter对象,它的responseType方法会返回数据的真实类型,比如 Call<IpModel>,它就会返回IpModel。adapt方法会创建ExecutorCallbackCall,它会将call的回调转发至UI线程。

接着回到ServiceMethod的 build方法,注释2处调用CallAdapter的responseType得到的是返回数据的真实类型。

注释3处调用createResponseConverter方法来遍历converterFactories列表中存储的Converter.Factory,并返回一个合适的Converter用来转换对象。此前我们在构建Retrofit 调用了addConverterFactory(GsonConverterFactory.create())将GsonConverterFactory(Converter.Factory的子类)添加到converterFactories列表中,表示返回的数据支持转换为Json对象。

注释4处遍历parseMethodAnnotation方法来对请求方式(比如GET、POST)和请求地址进行解析。注释5处对方法中的参数注解进行解析(比如@Query、@Part)。最后创建ServiceMethod类并返回。

接下来回过头来查看Retrofit的create方法,在调用了loadServiceMethod方法后会创建OkHttpCall,OkHttpCall的构造函数只是进行了赋值操作。紧接着调用serviceMethod.callAdapter.adapt(okHttpCall),callAdapter的adapt方法前面讲过,它会创建ExecutorCallbackCall,ExecutorCallbackCall的部分代码如下所示。

ExecutorCallbackCall(Executor callbackExecutor, Call delegate) {

this.callbackExecutor = callbackExecutor;

this.delegate = delegate;

}

@Override public void enqueue(final Callback callback) {

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

delegate.enqueue(new Callback() {//1

@Override public void onResponse(Call call, final Response 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 call, final Throwable t) {

callbackExecutor.execute(new Runnable() {

@Override public void run() {

callback.onFailure(ExecutorCallbackCall.this, t);

}

});

}

});

}

可以看出ExecutorCallbackCall是对Call的封装,它主要添加了通过callbackExecutor将请求回调到UI线程。

当我们得到Call对象后会调用它的enqueue方法,其实调用的是ExecutorCallbackCall的enqueue方法,而从注释1处可以看出ExecutorCallbackCall的enqueue方法最终调用的是delegate的enqueue方法。delegate从Retrofit的create方法的代码中我们知道它其实就是OkHttpCall。

3.Call的enqueue方法

接下来我们就来查看OkHttpCall的enqueue方法,代码如下所示。

public void enqueue(final Callback callback) {

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

okhttp3.Call call;

call.enqueue(new okhttp3.Callback() {//1

@Override public void onResponse(okhttp3.Call call, okhttp3.Response rawResponse)

throws IOException {

Response response;

try {

response = parseResponse(rawResponse);//2

} catch (Throwable e) {

callFailure(e);

return;

}

callSuccess(response);

}

}

注释1处调用了okhttp3.Call的enqueue方法。注释2处调用parseResponse方法:

Response parseResponse(okhttp3.Response rawResponse) throws IOException {

ResponseBody rawBody = rawResponse.body();

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

return Response.success(null, rawResponse);

}

ExceptionCatchingRequestBody catchingBody = new ExceptionCatchingRequestBody(rawBody);

try {

T body = serviceMethod.toResponse(catchingBody);//2

return Response.success(body, rawResponse);

} catch (RuntimeException e) {

catchingBody.throwIfCaught();

throw e;

}

}

根据返回的不同的状态码code值来做不同的操作,如果顺利则会调用注释2处的代码,接下来看toResponse方法里做了什么:

T toResponse(ResponseBody body) throws IOException {

return responseConverter.convert(body);

}

这个responseConverter就是此前讲过在ServiceMethod的build方法调用createResponseConverter方法返回的Converter,在此前的例子中我们传入的是GsonConverterFactory,因此可以查看GsonConverterFactory的代码,如下所示。

public final class GsonConverterFactory extends Converter.Factory {

@Override

public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations,

Retrofit retrofit) {

TypeAdapter<?> adapter = gson.getAdapter(TypeToken.get(type));

return new GsonResponseBodyConverter<>(gson, adapter);

}

}

在GsonConverterFactory 中有一个方法responseBodyConverter,它最终会创建GsonResponseBodyConverter:

final class GsonResponseBodyConverter implements Converter<ResponseBody, T> {

private final Gson gson;

private final TypeAdapter adapter;

GsonResponseBodyConverter(Gson gson, TypeAdapter adapter) {

this.gson = gson;

this.adapter = adapter;

}

@Override public T convert(ResponseBody value) throws IOException {

JsonReader jsonReader = gson.newJsonReader(value.charStream());
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

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

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

img

img

img

img

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

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

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:Android)

建议

当我们出去找工作,或者准备找工作的时候,我们一定要想,我面试的目标是什么,我自己的技术栈有哪些,近期能掌握的有哪些,我的哪些短板 ,列出来,有计划的去完成,别看前两天掘金一些大佬在驳来驳去 ,他们的观点是他们的,不要因为他们的观点,膨胀了自己,影响自己的学习节奏。基础很大程度决定你自己技术层次的厚度,你再熟练框架也好,也会比你便宜的,性价比高的替代,很现实的问题但也要有危机意识,当我们年级大了,有哪些亮点,与比我们经历更旺盛的年轻小工程师,竞争。

  • 无论你现在水平怎么样一定要 持续学习 没有鸡汤,别人看起来的毫不费力,其实费了很大力,这四个字就是我的建议!!!!!!!!!

  • 准备想说怎么样写简历,想象算了,我觉得,技术就是你最好的简历

  • 我希望每一个努力生活的it工程师,都会得到自己想要的,因为我们很辛苦,我们应得的。

  • 有什么问题想交流,欢迎给我私信,欢迎评论

【附】相关架构及资料

Android高级技术大纲

面试资料整理

内含往期Android高级架构资料、源码、笔记、视频。高级UI、性能优化、架构师课程、NDK、混合式开发(ReactNative+Weex)微信小程序、Flutter全方面的Android进阶实践技术

《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!

无论你现在水平怎么样一定要 持续学习 没有鸡汤,别人看起来的毫不费力,其实费了很大力,这四个字就是我的建议!!!!!!!!!

  • 准备想说怎么样写简历,想象算了,我觉得,技术就是你最好的简历

  • 我希望每一个努力生活的it工程师,都会得到自己想要的,因为我们很辛苦,我们应得的。

  • 有什么问题想交流,欢迎给我私信,欢迎评论

【附】相关架构及资料

[外链图片转存中…(img-59KhJXhX-1713447612334)]

[外链图片转存中…(img-ZNtursta-1713447612334)]

内含往期Android高级架构资料、源码、笔记、视频。高级UI、性能优化、架构师课程、NDK、混合式开发(ReactNative+Weex)微信小程序、Flutter全方面的Android进阶实践技术

《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值