Retrofit解析

本文深入分析了Retrofit的源码,从创建Retrofit对象、定义API、调用API方法,到ServiceMethod、OkHttpCall的工作原理,揭示了Retrofit如何实现HTTP请求和响应的转换。文中强调了动态代理、工厂模式在Retrofit中的应用,以及如何通过CallAdapter和Converters将网络响应数据转换为所需对象。
摘要由CSDN通过智能技术生成

一、整体思路

从使用方法出发,首先是怎么使用,其次是我们使用的功能在内部是如何实现的,实现方案上有什么技巧,有什么范式。全文基本上是对 Retrofit 源码的一个分析与导读,非常建议大家下载 Retrofit 源码之后,跟着本文,过一遍源码。

二、基本用例

2.1 创建 Retrofit 对象

Retrofit retrofit = new Retrofit.Builder()
    .baseUrl("https://api.github.com/")
    .addConverterFactory(GsonConverterFactory.create())
    .build();

builder 模式,外观模式(门面模式),这就不多说了,可以看看 stay 的 Retrofit分析-经典设计模式案例这篇文章。

2.2 定义 API 并获取 API 实例

public interface GitHubService {
  @GET("users/{user}/repos")
  Call<List<Repo>> listRepos(@Path("user") String user);
}

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

先看定义,非常简洁,也没有什么特别之处,除了两个注解:@GET 和 @Path。它们的用处稍后再分析,我们接着看创建 API 实例:retrofit.create(GitHubService.class)。这样就创建了 API 实例了,就可以调用 API 的方法发起 HTTP 网络请求了,太方便了。

但 create 方法是怎么创建 API 实例的呢?

public <T> T create(final Class<T> service) {
  // 省略非关键代码
  return (T) Proxy.newProxyInstance(service.getClassLoader(), 
      new Class<?>[] { service },
      new InvocationHandler() {
        @Override 
        public Object invoke(Object proxy, Method method, Object... args)
            throws Throwable {
          // 先省略实现
        }
      });
}

创建 API 实例使用的是动态代理技术

简而言之,就是动态生成接口的实现类(当然生成实现类有缓存机制),并创建其实例(称之为代理),代理把对接口的调用转发给 InvocationHandler 实例,而在 InvocationHandler 的实现中,除了执行真正的逻辑(例如再次转发给真正的实现类对象),我们还可以进行一些有用的操作,例如统计执行时间、进行初始化和清理、对接口调用进行检查等。

为什么要用动态代理?因为对接口的所有方法的调用都会集中转发到 InvocationHandler#invoke函数中,我们可以集中进行处理,更方便了。你可能会想,我也可以手写这样的代理类,把所有接口的调用都转发到 InvocationHandler#invoke 呀,当然可以,但是可靠地自动生成岂不更方便?

2.3 调用 API 方法

获取到 API 实例之后,调用方法和普通的代码没有任何区别:

Call<List<Repo>> call = github.listRepos("square");
List<Repo> repos = call.execute().body();

这两行代码就发出了 HTTP 请求,并把返回的数据转化为了 List<Repo>,太方便了!

现在我们来看看调用 listRepos 是怎么发出 HTTP 请求的。上面 Retrofit#create 方法返回时省略的代码如下:

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);
        OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args);
        return serviceMethod.callAdapter.adapt(okHttpCall);
      }
    });

如果调用的是 Object 的方法,例如 equalstoString,那就直接调用。如果是 default 方法(Java 8 引入),就调用 default 方法。这些我们都先不管,因为我们在安卓平台调用 listRepos,肯定不是这两种情况,那这次调用真正干活的就是这三行代码了(好好记住这三行代码,因为接下来很长的篇幅都是在讲它们 ? ):

ServiceMethod serviceMethod = loadServiceMethod(method);
OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args);
return serviceMethod.callAdapter.adapt(okHttpCall);

在继续分析这三行代码之前,我们先看看 Stay 在 Retrofit分析-漂亮的解耦套路 这篇文章中分享的流程图,完整的流程概览建议仔细看看这篇文章:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值