Android Retrofit2 源码分析(一)—— Retroift 的构建

Retrofit2 简介

做为当前 Android 最主流的网络框架(我个人认为)。

它基于 OkHttp3(square 的代表作) 做了十分优雅的封装,同时它作为大名鼎鼎的 square 公司的产品,我就不详细说它对 OkHttp3 的封装做到啥地步了
(^ _ ^")。

它可以通过十分简单的配置,来很好的满足各种业务场景,比如说可以使用自定义的适配器,转换器(这里最重要的是它可以和 RxJava 完美的相结合),代码简直优雅了十倍不止,同时它的使用也十分简单,可以通过不同的注解来定制一个 request...

它的功能我也不多说了,上面说的可能有点夸张,但我做为一个 Android 开发的小白那是对它推崇至极,赞不绝口!

接下来我将对如何构建一个 Retrofit 来做一个分析。

Retrofit 简单用例

apiService = new Retrofit.Builder().client(OkHttpManager.getInstance())
                    .addConverterFactory(GsonConverterFactory.create())
                    .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                    .baseUrl(ApiSetting.SERVER_URL)
                    .build()
                    .create(ApiService.class);

以上是我自己一个项目中创建 Retrofit 服务代理的代码,这里我们就根据这个流程,具体的去分析 Retrofit 的实现原理。

其实在 build() 方法之前,无非都是做一些配置,所以我们将重点放在 build() 方法和 creat() 方法中。

走进源码

build() 方法

先看源码

    public Retrofit build() {
      //如果 baseUrl 为空,那么抛出异常(Url都为空了,那还访问啥)
      if (baseUrl == null) {
        throw new IllegalStateException("Base URL required.");
      }
      //这里的 callFactory,就是我们上面示例中的自定义的 okhttp client, 
      //如果我们配置自定义的 client 的话,那么这里直接 new 一个默认的 client    
      okhttp3.Call.Factory callFactory = this.callFactory;
      if (callFactory == null) {
        callFactory = new OkHttpClient();
      }
      //这里则配置执行后的回调,我的示例中并没有配置  
      Executor callbackExecutor = this.callbackExecutor;
      if (callbackExecutor == null) {
        //这里跟 Builder 的时候有关,如果是 Android 环境下,那么会返回一个默认的 CallbackExecutor
        callbackExecutor = platform.defaultCallbackExecutor();
      }

      // Make a defensive copy of the adapters and add the default Call adapter.
      //这里就是我们配置的适配器,在示例中,我添加了RxJava 的相关适配器
      List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>(this.callAdapterFactories);
      //添加完我们添加的适配器 后会自动添加必须的适配器,这里的设置的回调便是上面的 callbackExecutor
      callAdapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor));

      // Make a defensive copy of the converters.
      
      //这里就是添加变流器的流程了,类似于适配器的添加,我们这里添加了 Gson 的相关转换器
      List<Converter.Factory> converterFactories =
          new ArrayList<>(1 + this.converterFactories.size());

      // Add the built-in converter factory first. This prevents overriding its behavior but also
      // ensures correct behavior when using converters that consume all types.
      
      //但是有一点不同的是,上面的适配器是先添加用户的再添加默认的,这里是反了一下,先添加默认的,再添加用户的。
      converterFactories.add(new BuiltInConverters());
      converterFactories.addAll(this.converterFactories);

      //这里依据我们配置的各种参数来生成一个 retrofit 的实例    
      return new Retrofit(callFactory, baseUrl, unmodifiableList(converterFactories),
          unmodifiableList(callAdapterFactories), callbackExecutor, validateEagerly);
    }

build 的流程非常简单,跟我们平常使用构造者模式的流程差不多,根据一系列的配置,最后在 build 方法中根据用户的配置和默认的设置创建出一个可以符合用户需求的对象。

接下来我们来看下,Retrofit 为我们添加的默认功能都做了什么。

默认添加的适配器

build() 方法中为我们添加了默认的适配器

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

这里传入了上面创建的 callbackExecutor,我们点进去看一下。

  CallAdapter.Factory defaultCallAdapterFactory(@Nullable Executor callbackExecutor) {
    // 如果 callbackExecutor 不为空,那么创建一个 ExecutorCallAdapterFactory
    if (callbackExecutor != null) {
      return new ExecutorCallAdapterFactory(callbackExecutor);
    }
    // 不然返回 DefaultCallAdapterFactory
    return DefaultCallAdapterFactory.INSTANCE;
  }

这里对之前传入的 callbackExecutor 做了判空,并返回不同结果,我们再回去看下 callbackExecutor 的创建。

  if (callbackExecutor == null) {
    callbackExecutor = platform.defaultCallbackExecutor();
  }

如果我们没有配置 callbackExecutor 的话,系统就会调用 platform.defaultCallbackExecutor()

不说了,再进去看下!

  @Nullable Executor defaultCallbackExecutor() {
   return null;
 }

纳尼?返回的是 null,其实不是,这里我们先去看 Builder() 方法

    public Builder() {
      this(Platform.get());
    }

这里调用了 Platform.get() 方法

  private static final Platform PLATFORM = findPlatform();

  static Platform get() {
    return PLATFORM;
  }

PLATFORM 是调用了 findPlatform() 方法

  private static Platform findPlatform() {
    try {
      Class.forName("android.os.Build");
      if (Build.VERSION.SDK_INT != 0) {
        //这里可以看到 new 了一个 Androdi 对象
        return new Android();
      }
    } catch (ClassNotFoundException ignored) {
    }
    try {
      Class.forName("java.util.Optional");
      return new Java8();
    } catch (ClassNotFoundException ignored) {
    }
    return new Platform();
  }
  static class Android extends Platform {
   //在 Android 环境下,调用 platform.defaultCallbackExecutor() 就是这里
    @Override public Executor defaultCallbackExecutor() {
      return new MainThreadExecutor();
    }
    @Override CallAdapter.Factory defaultCallAdapterFactory(@Nullable Executor callbackExecutor) {
      if (callbackExecutor == null) throw new AssertionError();
      return new ExecutorCallAdapterFactory(callbackExecutor);
    }

    static class MainThreadExecutor implements Executor {
      private final Handler handler = new Handler(Looper.getMainLooper());

      @Override public void execute(Runnable r) {
        handler.post(r);
      }
    }
  }

可以看到调用 platform.defaultCallbackExecutor() 的话,会生成 MainThreadExecutor

所以我们在 Android 中使用的话,一般不会返回 DefaultCallAdapterFactory.INSTANCE

但是 DefaultCallAdapterFactory 的代码十分简单,我们可以去了解下。

那我们先看下 DefaultCallAdapterFactory 的作用。

DefaultCallAdapterFactory

/**
 * Creates call adapters for that uses the same thread for both I/O and application-level
 * callbacks. For synchronous calls this is the application thread making the request; for
 * asynchronous calls this is a thread provided by OkHttp's dispatcher.
 */
final class DefaultCallAdapterFactory extends CallAdapter.Factory {
  static final CallAdapter.Factory INSTANCE = new DefaultCallAdapterFactory();

  @Override
  public CallAdapter<?, ?> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
    //如果我们 ApiService 接口中请求中返回的类型不是 Call 对象,那么就返回 null
    if (getRawType(returnType) != Call.class) {
      return null;
    }
    
    //1
    final Type responseType = Utils.getCallResponseType(returnType);
    return new CallAdapter<Object, Call<?>>() {
      @Override public Type responseType() {
        return responseType;
      }

      @Override public Call<Object> adapt(Call<Object> call) { 
        //直接返回 call
        return call;
      }
    };
  }
}

对于这段代码,先看它的注释,大致意思是回调和请求在同一线程,如果是异步请求,这个线程有 OkHttp 提供。

然后我们再去看下注释 1 的 Utils.getCallResponseType(returnType) 方法作用

  static Type getCallResponseType(Type returnType) {
    // 这里对返回类型做了判断,如果不是 Call<Foo> 或者 Call<? extent Foo>,那么就抛出异常。
    if (!(returnType instanceof ParameterizedType)) {
      throw new IllegalArgumentException(
          "Call return type must be parameterized as Call<Foo> or Call<? extends Foo>");
    }
    // 返回获取到的返回值类型,以便后续 Conveeter 做类型转换
    return getParameterUpperBound(0, (ParameterizedType) returnType);
  }

现在可以知道之前注释1 中的代码是用来获取请求返回值类型的。

DefaultCallAdapterFactory 作用总结

根据上面的分析,可以知道 DefaultCallAdapterFactory 中 回调和请求在同一线程,如果是异步请求,这个线程由 OkHttp 提供,而且对获取到的 Call 不做处理,直接返回。

接下来去分析下 ExecutorCallAdapterFactory, 因为我们使用的时候,它才是默认的 CallAdapter。

ExecutorCallAdapterFactory

final class ExecutorCallAdapterFactory extends CallAdapter.Factory {
  final Executor callbackExecutor;

  ExecutorCallAdapterFactory(Executor callbackExecutor) {
    this.callbackExecutor = callbackExecutor;
  }

  @Override
  public CallAdapter<?, ?> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
    if (getRawType(returnType) != Call.class) {
      return null;
    }
    final Type responseType = Utils.getCallResponseType(returnType);
    return new CallAdapter<Object, Call<?>>() {
      @Override public Type responseType() {
        return responseType;
      }

      @Override public Call<Object> adapt(Call<Object> call) {
        //1
        return new ExecutorCallbackCall<>(callbackExecutor, call);
      }
    };
  }
  ······
 }

基本上和 DefaultCallAdapterFactory 一样,有了上面 DefaultCallAdapterFactory 的源码分析,这里就不多做介绍,唯一不同的是 adapt 方法中,
它 new 了一个 ExecutorCallbackCall 对象,这里就是请求之后的回调,关于这里具体的内容,我打算在之后的 Retrofit 动态代理相关的内容去说,我们现在只需要知道它的作用就好了。

默认添加的 转换器(变流器)

接下来我们来看下,Retrofit 为我们添加的,而且特意添加到第一个位置的 BuiltInConverter。

BuiltInConverter

  @Override
  public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations,
      Retrofit retrofit) {
    //如果返回数据的类型是 ResponseBody
    if (type == ResponseBody.class) {
      //这里根据数据处理是在 streaming 还是 buffer中做了判断,因为两者处理方式不同,所以分开处理。
      return Utils.isAnnotationPresent(annotations, Streaming.class)
          ? StreamingResponseBodyConverter.INSTANCE
          : BufferingResponseBodyConverter.INSTANCE;
    }
    //这一步的意图在于安全退出相关操作
    if (type == Void.class) {
      return VoidResponseBodyConverter.INSTANCE;
    }
    return null;
  }

  @Override
  public Converter<?, RequestBody> requestBodyConverter(Type type,
      Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) {
    //这里判断请求的类型是不是 OkHttp 中的 RequestBody,因为 Retrofit 就是对 OkHttp 做了十分棒的封装。 
    if (RequestBody.class.isAssignableFrom(Utils.getRawType(type))) {
      return RequestBodyConverter.INSTANCE;
    }
    return null;
  }

这里我直接贴了 BuiltInConverter 唯二的方法,一个做为返回 body 的处理(responseBodyConverter),一个做为请求 body 的处理(requestBodyConverter)。

两者其实都是对数据的类型或者环境做了判断,并给予不同的处理方式。

以上涉及到的各种 Converter 都是 BuiltInConverter 的内部类,作用都跟名字一样清晰,代码也十分简单,没什么复杂的操作,我这里贴一下就不详解了,如下。

static final class VoidResponseBodyConverter implements Converter<ResponseBody, Void> {
    static final VoidResponseBodyConverter INSTANCE = new VoidResponseBodyConverter();

    @Override public Void convert(ResponseBody value) {
      value.close();
      return null;
    }
  }

  static final class RequestBodyConverter implements Converter<RequestBody, RequestBody> {
    static final RequestBodyConverter INSTANCE = new RequestBodyConverter();

    @Override public RequestBody convert(RequestBody value) {
      return value;
    }
  }

  static final class StreamingResponseBodyConverter
      implements Converter<ResponseBody, ResponseBody> {
    static final StreamingResponseBodyConverter INSTANCE = new StreamingResponseBodyConverter();

    @Override public ResponseBody convert(ResponseBody value) {
      return value;
    }
  }

  static final class BufferingResponseBodyConverter
      implements Converter<ResponseBody, ResponseBody> {
    static final BufferingResponseBodyConverter INSTANCE = new BufferingResponseBodyConverter();

    @Override public ResponseBody convert(ResponseBody value) throws IOException {
      try {
        // Buffer the entire body to avoid future I/O.
        return Utils.buffer(value);
      } finally {
        value.close();
      }
    }
  }

  static final class ToStringConverter implements Converter<Object, String> {
    static final ToStringConverter INSTANCE = new ToStringConverter();

    @Override public String convert(Object value) {
      return value.toString();
    }
  }

BuiltInConverter 作用总结

其实它就是起到一个统筹的作用,做为 Retrofit 的内置 Converter,它根据需要处理的对象的类型以及环境不同来调用相适应的 Converter 来处理对应的任务。

Retroift 的 构造方法

其实到这里,我们已经差不多分析完了 Retrofit 默认配置的一些模块,我们回到 build() 方法中的最后一步。

    return new Retrofit(callFactory, baseUrl, unmodifiableList(converterFactories),
        unmodifiableList(callAdapterFactories), callbackExecutor, validateEagerly);

这里就是创建了一个 retrofit 实例

  Retrofit(okhttp3.Call.Factory callFactory, HttpUrl baseUrl,
      List<Converter.Factory> converterFactories, List<CallAdapter.Factory> callAdapterFactories,
      @Nullable Executor callbackExecutor, boolean validateEagerly) {
    this.callFactory = callFactory;
    this.baseUrl = baseUrl;
    this.converterFactories = converterFactories; // Copy+unmodifiable at call site.
    this.callAdapterFactories = callAdapterFactories; // Copy+unmodifiable at call site.
    this.callbackExecutor = callbackExecutor;
    this.validateEagerly = validateEagerly;
  }

到最后很简单,将配置好的参数都做为 Retrofit 构造时的初始值。

最后 Retrofit 是如何运用我们配置好的适配器,转换器等等工具呢。

还记得简单用例中最后的 create() 方法吗,Retrofit 在这个方法中,使用动态代理创建了一个代理供我们使用,而我们配置的这些适配器转换器等工具将在这里使用,Retrofit 会很智能的根据这些参数来生成我们想要的代理,我们只需要负责用就好了。

总结

这就是 Retrofit 关于 build 的源码分析,后面我会再深入到 create() 方法中,去看一下 Retrofit 最为核心的代码,是如何实现的。

Android Retrofit2 源码分析(二)—— Retrofit 的动态代理

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,456评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,370评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,337评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,583评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,596评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,572评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,936评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,595评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,850评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,601评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,685评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,371评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,951评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,934评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,167评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,636评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,411评论 2 342