展开说说Android之Retrofit详解_源码解析

Retrofit作为当下Android开发最流行的网络请求框架之一,基于上一篇《展开说说Android之Retrofit详解_使用篇》本文继续分析一下Retrofit的源码实现。

对我个人来说学习一个新事物,一般是三个步骤:做什么、怎么用、为什么。做什么的大家已经明了要不然也不会点开看、怎么用上一篇已经分析了,至于“为什么” 本文将从以下几个角度分析Retrofit源码:

A、Retrofit框架有哪些核心类和接口

B、@GET、@POST等这些注解的作用

C、听说Retrofit是封装的Okhttp,源码中怎么实现的呢

D、为什么OKHttp异步请求是在子线程返回但Retroift却可以在主线程返回

E、梳理一下我们发起请求时的完整流程

F、最后简单总结一下Retrofit的优缺点

  • Retrofit框架有哪些核心类和接口

1、‌Retrofit类
作为框架的入口点,结构和OKHttpClient类似,也有一个一个Builder内部类,Builerd提供了包括设置基础URL、转换器工厂、调用适配器等核心组件还有一个熟悉的build方法用来创建Retrofit实例。他还有一个非常重要的方法create是负责创建请求对象的。

2、‌ServiceMethod类
解析接口方法的注解信息(如@GET、@POST等),创建请求对象,最后把方法参数转换为发送HTTP请求携带的参数。

它是个抽象类,只有一个普通方法parseAnnotations负责解析注解并创建请求对象,负责准备工作,二另一个invoke却是个抽象方法,它时我们发起请求的核心方法。

3、RequestFactory

其实这个才是真正解析注解并创建请求对象的,‌ServiceMethod的parseAnnotations方法就是调用了RequestFactory的同名方法parseAnnotations完成的实际工作。还能动态生成HTTP请求的URL、Header和Body等.

4、HttpServiceMethod

第二点提到ServiceMethod的抽象方法invoke,它的实现是在子类HttpServiceMethod中。这里invoke方法会创建另一个核心类OkHttpCall

5、各个‌注解类(如@GET、@POST、@Query等)
我们知道使用Retrofit肯定离不开注解的使用,每个注解就是一个类,定义API请求的元数据,他们包括请求方法、路径、参数等,极大的简化HTTP请求的配置。他们都是再http目录下,数量很多,截图为一部份:

6、‌OkHttpCall类
封装OkHttpCall对象,负责Retrofit与OkHttp之间的交互,这里会调用OKHttp的enqueue和execute执行网络请求然后将返回报文给到Retrofit的回调方法最终给到调用者来处理响应

7、‌Converter接口及其实现类
负责请求/响应数据的序列化与反序列化,例如将JSON响应转换为Java对象。一般用Gson或、Moshi。

5、‌Response类
封装服务器返回的原始响应数据,包括状态码、响应头和响应体。

二、@GET、@POST等这些注解的作用

Retrofit的注解一般分为三种种,用于定义网络请求类型和配置请求参数以及拥有特定技能的注解

  1. 定义网络请求类型

包括@GET@POST@PUT@DELETE等,就是我们常用的接口请求类型。

  1. 定义请求参数的注解:

@Path 动态替换URL路径中的占位符(如users/{index}中的{index})。‌

@Query:添加单个查询参数(如?key=value

@QueryMap:以Map形式添加多个查询参数。

@Field/@FieldMap二者都用于表单提交,自动进行URL编码@Field("key")绑定单个字段@FieldMap Map<String, String>则用于绑定多个字段。

@Body 直接序列化对象为请求体(如JSON),需配合Gson或Moshi转换器。

  1. 用特定技能的注解

@Url‌动态指定完整请求URL,覆盖Retrofit实例设置的全局的baseUrl。

@Headers:静态添加请求头(如@Headers("Cache-Control: max-age=3600")

@Header:动态添加请求头(通过方法参数传入)。

@Multipart 用于文件上传,需配合@Part@PartMap声明分块数据。

@Streaming 标记响应体以流式处理,适用于大文件下载。

三、听说Retrofit是封装的Okhttp,源码中怎么实现的呢

就是上面第一部分第6点中提到的OkHttpCall封装OkHttpCall对象,负责Retrofit与OkHttp之间的交互,这里会调用OKHttp的enqueue和execute执行网络请求然后将返回报文给到Retrofit的回调方法最终给到调用者来处理响应。

1、先看它的导包:

2、以enqueue方法为例:

上面可以看出,OkHttpCall中enqueue方法会调用OKHttp的enqueue方法,这块跟咱们自己使用OKHttp一样的,不过这里是又多经历了一层Retrofit的回到才给到调用者。

四、为什么OKHttp异步请求是在子线程返回但Retroift却可以在主线程返回

Retrofit中有个Platform类,他有一个内部类Android,也是它的子类。 Android类中有一个MainThreadExecutor类继承Executor,并且它内部有一个使用Looper.getMainLooper()创建的Handler,看完这里就直到为啥再主线程返回了吧。

五、梳理一下我们发起请求时的完整流程

public <T> T getServer(Class<T> cls, String baseUrl){
    if (retrofit == null){
        retrofit = new Retrofit.Builder()
                .baseUrl(baseUrl)
                .client(getClient())
                .addConverterFactory(GsonConverterFactory.create())
                .build();
    }
    return retrofit.create(cls);
}

以此为例,这段完整代码,再上一篇文章已经提供:

上面提到Retrofit也是建造者模式,他也有内部类Builder。

1、Retrofit.Builder()会创建一个PlatForm对象。

2、baseUrl(baseUrl) 设置请求接口的公共Url

/**
 * Set the API base URL.
  * @see #baseUrl(HttpUrl)
 */
public Builder baseUrl(String baseUrl) {
  Objects.requireNonNull(baseUrl, "baseUrl == null");
  return baseUrl(HttpUrl.get(baseUrl));
}

3、.client(getClient()) 用来设置OkhttpClient。

注:设置超时时间、拦截器、cookie等都是这个Okhttpclient对象中。

 * The HTTP client used for requests.
 *
 * <p>This is a convenience method for calling {@link #callFactory}.
 */
public Builder client(OkHttpClient client) {
  return callFactory(Objects.requireNonNull(client, "client == null"));
}

4、addConverterFactory设置转换器

5、build()建造者模式,构建Retrofit对象

7、非常非常重要的一个方法,create

这里用到了动态代理Proxy.newProxyInstance,在你用create方法构建的请求对象调用接口后回调InvocationHandler的invoke方法。然后我们呢顺着捋一捋你发起请求后的流程,从loadServiceMethod(method).invoke(args)开始:

他会调用ServiceMethodparseAnnotations方法,之前提到过的parseAnnotations

方法和抽象方法invoke:

RequestFactory也是建造者模式,有个Builder内部类,其内部也有build方法 它回调用parseMethodAnnotation方法解析我们设置的注解。

最终return HttpServiceMethod.parseAnnotations(retrofit, method, requestFactory);

返回CallAdapted对象,而CallAdapted的父类是HttpServiceMethodHttpServiceMethod的父类是ServiceMethod

HttpServiceMethodcreateCallAdapter方法,然后到Retrofit的callAdapter

方法,再调用nextCallAdapter方法,然后这一行CallAdapter<?, ?> adapter = callAdapterFactories.get(i).get(returnType, annotations, this);到了DefaultCallAdapterFactory类的get方法:

再回到loadServiceMethod(method).invoke(args)的后半部分,invoke(args)他调用的是ServiceMethod中抽象方法invoke的实现类重写的invoke方法就是上面get方法中new CallAdapter时重写的方法。

记住这个executor就是Platform类中Android类的MainThreadExecutor的对象,它是callbackExecutor赋值的,而callbackExecutor时再Retrofit的build方法时传过来的。

CompletableFutureCallAdapterFactory中触发adapter时。

然后也是抽象方法adapt,再到实现类DefaultCallAdapterFactory

enqueue方法:

最后callbackExecutor.enqueue方法又回到了,MainThreadExecutor

execute方法,因此在主线程给开发者返回了报文

想了解Retrofit使用的朋友可以参考上一篇《展开说说Android之Retrofit详解_使用篇》。

个人总结记录,才疏学浅,如有错误,欢迎指正,多谢。 

    评论 1
    添加红包

    请填写红包祝福语或标题

    红包个数最小为10个

    红包金额最低5元

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

    抵扣说明:

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

    余额充值