Retrofit源码浅析,2024年最新c语言程序设计需求分析

那么接口listReops的返回类型可谓Observable< T>。

build最后初始化了转换器工厂类的集合,转换器工厂主要负责网络响应的解析,如果我们设置为GsonConverterFactory,那么就可以使用Gson解析网络结果,如果设置为ProtoConverterFactory,则可以使用ProtoBuf解析网络结果。

2、实现网络接口


在示例中,我们定义了网络接口Githubservice,然后使用创建的Retrofit对象的create方法来实现该接口,网络接口的实现为Retrofit最重要的逻辑,而网络接口的实现就是使用Java的动态代理实现的。create方法的调用和实现如下:

GitHubService githubService = retrofit.create(GitHubService.class);

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

//创建ServiceMthod对象,完成接口方法的解析和封装

ServiceMethod serviceMethod = loadServiceMethod(method);

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

return serviceMethod.callAdapter.adapt(okHttpCall);

}

});

}

Retrofit的create方法的主要逻辑就是返回一个GithubService接口的代理对象。注意这里是代理对象,并不是通过implement关键字实现GithubService接口的实现类,当我们调用代理对象的接口方法时,如调用listRepos方法时:

Call<Lsit> octocat = githubSerivce.listRepos(“octocat”);

就会触发InvocationHandler的invoke方法的调用来完成listRepos接口的实现:返回一个Call< T>对象。

在invoke方法中,调用loadServiceMethod加载一个ServiceMethod对象,如果已经加载过了,则会从缓存中获取,如果没有缓存,则会创建一个新的ServiceMethod对象,在创建过程中完成了对网络接口方法的解析,进而封装成一个ServiceMethod对象。ServiceMethod对象中的成员变量如下:

final class ServiceMethod<R,T>{

final okhttp3.Call.Factory callFactory;

final CallAdapter<R,T> callAdapter;

private final HttpUrl baseUrl;

private final Converter<RespinseBody,R> respinserConverter;

private final String httpMethod; //请求方法:POST GET等

private final String relativeUrl;

private final Headers headers; //请求头

private final MediaType contentType;

}

这些成员变量大部分都是通过解析网络接口方法的注解完成初始化的。在获取到ServiceMethod对象后,使用它完成OkHttpCall< Object>对象的创建。最后通过代码:

return serviceMethod.callAdapter.adapt(okHttpCall);

返回一个对象。这个对象在当前示例下返回的是一个 ExecutorCallbackCall对象,它的创建过程还是比较复杂的,首先serviceMethod中的callAdapter对象是由createCallAdapter创建,而 createCallAdater内部是使用Retrofit对象来获取一个CallAdapter对象,createCallAdapter的调用和实现如下:

public ServiceMethod build() {

callAdapter = createCallAdapter();

}

private CallAdapter<?> createCallAdapter() {

try {

return retrofit.callAdapter(returnType, annotations);

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

throw methodError(e, “Unable to create call adapter for %s”, returnType);

}

}

callAdapter方法会遍历CallAdapter.Factory集合adapterFactories,根据网络接口方法的返回值来匹配CallAdapter对象,进而返回对应的CallAdapter。Retrofit的callAdapter方法的实现如下:

//Retrofit.java

public CallAdapter<?> callAdapter(Type returnType, Annotation[] annotations) {

return nextCallAdapter(null, returnType, annotations);

}

public CallAdapter<?> nextCallAdapter(CallAdapter.Factory skipPast, Type returnType,

Annotation[] annotations) {

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

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

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

//遍历CallAdapter.Factory集合

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

//根据网络接口的返回类型匹配相对应的CallAdapter.Factroy,进而获取CallAdapter对象

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

if (adapter != null) {

return adapter;

}

}

throw new IllegalArgumentException(builder.toString());

}

之前在创建Retrofit对象的时候,会默认添加一个ExecutorCallAdapterFactroy对象到CallAdapter.Factory的集合中。

所以在遍历CallAdapter.Factroy集合遍历到ExecutorCallAdapterFactory对象时,就会调用该对象的get方法获取一个CallAdapter对象:

//ExecutorCallAdapterFactory.java

@Override

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

Class<?> rawType = getRawType(returnType);

// 如果匹配的类型不为Call则返回null

if (rawType != Call.class) {

return null

}

final Type responseType = Utils.getCallResponseType(returnType);

//返回一个CallAdapter对象

return new CallAdapter<Object,Call<?>>{

@Override

public Type responseType(){

return responseType

}

@Override

public Call adapter(Call call){

return new ExecutorCallback<>(callbackExecutor,call);

}

}

}

在get方法中会根据网络接口的返回类型进行匹配,如果返回类型不为Call,则返回null,如果为Call类型,比如网络接口方法listRepos的返回类型为Call,那么就会通过判断来返回一个CallAdapter对象。再回到之前的代码:

serviceMethod.callAdapter.adapter(okHttpCall);

所以serviceMethod.callAdapter实际上是获取的是CallAdapter对象,CallAdapter对象的adapter方法会返回一个ExecutorCallbackCall对象。

所以,如果网络接口的返回类型为Call类型,那么在InvocationHandler的invoke方法中返回对象的类型为ExecutorCallbackCall。

3、网络请求的发送


通过网络接口的的实现可知,调用接口方法如下:

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

返回的Call对象实际上是ExecutorCallbackCall对象,所以接下来我们使用Call对象发送网络请求,如异步网络请求:

octocat.enqueue(mCallback);

实际上执行的是ExecutorCallbackCall中的enqueue方法,enqueue方法的实现如下:

@Override

public void enqueue(final Callback callback) {

call.enqueue(new okhttp3.Callback() {

//内部使用okhttp完成异步请求

@Override

//网络成功的回调

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

throws IOException {

Response response;

try {

response = parseResponse(rawResponse);

} catch (Throwable e) {

callFailure(e);

return;

}

callSuccess(response);

}

});

在enqueue方法内部,最终使用OkHttp执行网络请求,网络响应或失败都会通过MainThreadExecutor分发到主线程。

总结


  1. 从Retrofit的build方法 建造出一个 Retrofit对象,过程中有两个重要的工厂集合:

(1)adapterFactories集合,是CallAdapter的工厂实现类,里面装着网络回调执行器callbackExecutor(就是绑定主线程的Handler)

(2)converterFactories集合,Converter的工厂实现类,里面装着网络响应转化器,比如说Gson

  1. 网络接口的实现为Retrofit的最终要的逻辑,也就是其create方法

通过动态代理将网络接口转化成一个ServiceMethod对象,这个ServiceMethod中封装了网络请求的所有信息,然后通过 OkHttpCall<>(ServiceMehtod,args) 来封装成一个OkhttpCall对象,最后用这个OkHttpCall通过callAdapter方法 遍历一开始的adapterFactories集合,通过get方法最终来返回与网络接口匹配的CallAdapter对象。

  1. 通过create最终创造的CallAdapter对象可以通过调用其接口方法其实现一个同步/异步请求。

在异步请求中,enqueue实际上就是调用CallAdapter的enqueue方法 通过OkHttp实现网络请求,执行的结果通过MainThreadExecutor对象回调到主线程中。

关于OkHttp和Retroift疑问


有人就会问了,为什么Retrofit的网络请求是基于Okhttp,我们要去用Retrofit,而不是直接去用OkHttp呢?

我们先来看看OkHttp的特点

  • 支持SPDY,因此可以同一IP多个连接共享同一个socket(SPDY并不是一种用于替代HTTP的协议,而是对HTTP协议的增强)

  • 在Http/2不可用时, 连接池可极大减少延时;

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

深知大多数同学面临毕业设计项目选题时,很多人都会感到无从下手,尤其是对于计算机专业的学生来说,选择一个合适的题目尤为重要。因为毕业设计不仅是我们在大学四年学习的一个总结,更是展示自己能力的重要机会。

因此收集整理了一份《2024年计算机毕业设计项目大全》,初衷也很简单,就是希望能够帮助提高效率,同时减轻大家的负担。
img
img
img

既有Java、Web、PHP、也有C、小程序、Python等项目供你选择,真正体系化!

由于项目比较多,这里只是将部分目录截图出来,每个节点里面都包含素材文档、项目源码、讲解视频

如果你觉得这些内容对你有帮助,可以添加VX:vip1024c (备注项目大全获取)
img

尤其是对于计算机专业的学生来说,选择一个合适的题目尤为重要。因为毕业设计不仅是我们在大学四年学习的一个总结,更是展示自己能力的重要机会。**

因此收集整理了一份《2024年计算机毕业设计项目大全》,初衷也很简单,就是希望能够帮助提高效率,同时减轻大家的负担。
[外链图片转存中…(img-bZiPzl5S-1712532824987)]
[外链图片转存中…(img-UBOXDVbi-1712532824988)]
[外链图片转存中…(img-ccEaYpFp-1712532824989)]

既有Java、Web、PHP、也有C、小程序、Python等项目供你选择,真正体系化!

由于项目比较多,这里只是将部分目录截图出来,每个节点里面都包含素材文档、项目源码、讲解视频

如果你觉得这些内容对你有帮助,可以添加VX:vip1024c (备注项目大全获取)
[外链图片转存中…(img-IFz9NGY8-1712532824989)]

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值