Android网络请求库【Retrofit 2.9.0】基本用法与原理分析


Retrofit官网:https://square.github.io/retrofit/
Github地址:https://github.com/square/retrofit


前言

Retrofit是Square公司开发的一款Android网络请求库,Retrofit仅负责网络请求接口的封装,它使用运行时注解的方式提供请求参数的配置功能,底层基于OkHttp实现真正的网络请求。

如果还不了解OkHttp框架,强烈建议先阅读Android 网络请求库OkHttp基本原理与实现再来阅读本篇文章,会更加酣畅淋漓哦~

本文所提及的网络请求如无特殊说明,都是异步网络请求

为什么选择Retrofit(与其他主流框架对比)

现在市场上比较主流的网络请求框架有:

  • android-async-http(作者停止维护、不推荐使用)
  • Volley(谷歌)
  • OkHttp(Square)
  • Retrofit(Square)

一图让你了解全部的网络请求库和他们之间的区别!


Retrofit基本用法

1. 导入库

    implementation("com.squareup.okhttp3:okhttp:4.9.3")
    // define a BOM and its version
    implementation(platform("com.squareup.okhttp3:okhttp-bom:4.9.3"))
    implementation("com.squareup.okhttp3:logging-interceptor")

    implementation 'com.squareup.retrofit2:retrofit:2.9.0'
    implementation("com.squareup.retrofit2:converter-gson:2.9.0") //支持返回值为Gson类型的数据

默认情况下,Retrofit只能将数据反序列化为OkHttp的ResponseBody类型,并且它只能接受@Body注解的RequestBody类型。

除了默认情况,我们也可以添加转换器以支持其他类型。

  • Gson: com.squareup.retrofit2:converter-gson
  • Jackson: com.squareup.retrofit2:converter-jackson
  • Moshi: com.squareup.retrofit2:converter-moshi
  • Protobuf: com.squareup.retrofit2:converter-protobuf
  • Wire: com.squareup.retrofit2:converter-wire
  • Simple XML: com.squareup.retrofit2:converter-simplexml
  • JAXB: com.squareup.retrofit2:converter-jaxb
  • Scalars (primitives, boxed, and String): com.squareup.retrofit2:converter-scalars

2. 注解分类

Retrofit注解分为三大类,分别是请求方法注解、标记类注解和参数类注解。

请求方法注解有8种:GET/POST/PUT/DELETE/HEAD/PATCH/OPTIONS/HTTP,前7种与HTTP请求方法是对应的,最后的HTTP可以替换前面七种,也可以扩展请求方法。

标记类注解有3种:FormUrlEncoded、Multipart、Streaming。

参数类注解有Header、Headers、Body、Path、Field、FieldMap、Query、QueryMap、Part、PartMap等。

3. GET网络请求

首先编写请求网络接口

open interface ApiService {
    @GET("users/{user}/repos")
    fun listRepos(@Path("user") user: String?): Call?>?
}

@GET 注解指定当前网络请求方式,注解参数是访问地址,方法返回Call?>类型的数据。@Path注解用来动态配置Url地址,@Path("user")对应@GET注解中的{user},即使用传入的 user: String?值动态替换{user}

接下来创建Retrofit对象,创建接口类(动态代理)调用网络请求方法,得到Call并发起异步请求,回调的Callback运行在UI线程。

val retrofit = Retrofit.Builder()
        .baseUrl("https://api.github.com/")
        .client(okHttpClient)
        .addConverterFactory(GsonConverterFactory.create())  //数据转换器Factory
        .build()
val listRepos = retrofit.create(ApiService::class.java).listRepos("octocat")
listRepos?.enqueue(object : Callback?> {
    override fun onResponse(call: Call?>, response: Response?>) {
        Log.d("retrofit", response.toString())
    }

    override fun onFailure(call: Call?>, t: Throwable) {

    }
})

请求的Url是由baseUrl和@GET注解参数拼接出来的:https://api.github.com/users/octocat/repos

一般情况下为了更准确地去查找网络数据,我们需要在Url中添加查询参数,这种情况可以使用Query指定查询条件。例如根据id查找数据,我们修改代码如下:

@GET("users/{user}/repos")
fun listRepos(@Path("user") user: String?, 
              @Query("id") id: Int?): Call?>?
val listRepos = retrofit.create(ApiService::class.java).listRepos("octocat", 132935648)

这样请求Url变为:https://api.github.com/users/octocat/repos?id=132935648

如果有多个查询参数使用@QueryMap

@GET("users/{user}/repos")
fun listRepos(@Path("user") user: String?,
              @QueryMap map:HashMap): Call?>?
val hashMap = HashMap()
hashMap.put("id", 132935648)
val listRepos = retrofit.create(ApiService::class.java).listRepos("octocat", hashMap)

4. POST网络请求

POST请求最常见的情况是传输键值对的数据类型,使用@Field注解就可以为POST请求添加键值对

@FormUrlEncoded
@POST("user/edit")
fun listRepos(@Field("first_name") first: String,
              @Field("last_name") last: String, ): Call?>?
val listRepos = retrofit.create(ApiService::class.java).listRepos("张", "三")

@FormUrlEncoded表明这是一个表单请求,使用@Field注解标注对应的键值对。

POST请求除了传输键值对,还可以传输JSON字符串,对应注解@Body。

package android.com.retrofit
data class User(val id: Int,
                val age: Int,
                val school: String) {
    constructor() : this(999, 16, "abc")
}
@POST("user/edit")
fun listRepos(@Body user: User): Call?>?
val listRepos = retrofit.create(ApiService::class.java).listRepos(User())

上传单个文件


 * @param photo 上传的文件
 * @param desc 文件描述(简单的键值对)
 */
@Multipart //表示允许多个part
@POST("user/photo")
fun uploadPhoto(@Part photo: MultipartBody.Part,
                @Part("desc") desc:
val file = File("文件路径")
val create = file.asRequestBody("image".toMediaTypeOrNull())
val photo = MultipartBody.Part.createFormData("photos", "aaa", create)
val requestBodyDesc = "picture".toRequestBody(null)
val listRepos = retrofit.create(ApiService::class.java).uploadPhoto(photo,requestBodyDesc)

上传多个文件
与上传单个文件类似,使用Map封装上传的文件,用@PartMap注解标注

更多用法可参考Carson带你学Android:网络请求库Retrofit使用教程(含实例讲解)

Retrofit原理解析

Retrofit最终的目的是通过使用大量的设计模式进行功能模块的解耦,使得网络请求过程变得更加简单流畅。

下图可以直观对比出一般网络请求流程与Retrofit请求的区别


Retrofit流程

详细步骤如下:

  1. 通过解析网络请求接口的注解配置网络请求参数
  2. 通过动态代理生成网络请求对象
  3. 通过网络请求适配器将网络请求对象进行平台适配(平台包括:Android、Rxjava、Guava和java8)
  4. 通过网络请求执行器发送网络请求
  5. 通过数据转换器解析服务器返回的数据
  6. 通过回调执行器切换线程(子线程 ->>主线程)
  7. 用户在主线程处理返回结果
主要角色说明

源码分析(基于Retrofit 2.9.0)

我们从Retrofit最基本的使用方式作为切入口,一步步深入源码探索Retrofit实现原理。

Retrofit使用主要分为以下几步:

  1. 创建Retrofit对象(建造者模式)
  2. 实例化接口类并调用请求方法(动态代理)
  3. 使用第2步返回的Call发起网络请求,Callback回调会运行在UI线程

接下来展开分析:

1. Retrofit.Builder()

因为Retrofit可配置的参数较多,所以采用建造者模式创建Retrofit实例。

Builder类主要代码如下:

  public static final class Builder {
    private final Platform platform;
    private @Nullable okhttp3.Call.Factory callFactory;
    private @Nullable HttpUrl baseUrl;  //网络请求基本地址
    private final List converterFactories = new ArrayList<>();   //用于创建Converter.Factory
    private final List callAdapterFactories = new ArrayList<>();   //用于创建CallAdapter.Factory
    private @Nullable Executor callbackExecutor;    //切换线程执行回调任务(默认是主线程)
    private boolean validateEagerly;

    //指定OkHttpClient
    public Builder client(OkHttpClient client) {  
      return callFactory(Objects.requireNonNull(client, "client == null"));
    }

    //设置baseUrl
    public Builder baseUrl(URL baseUrl) {  
      Objects.requireNonNull(baseUrl, "baseUrl == null");
      return baseUrl(HttpUrl.get(baseUrl.toString()));
    }

    /** 添加自定义的Converter Factory:用于创建数据转换器Converter  */
    public Builder addConverterFactory(Converter.Factory factory) {
      converterFactories.add(Objects.requireNonNull(factory, "factory == null"));
      return this;
    }

    /**
     * Add a call adapter factory for supporting service method return types other than {@link
     * Call}.  添加自定义的CallAdapter Factory:用于创建网络请求适配器CallAdapter
     */
    public Builder addCallAdapterFactory(CallAdapter.Factory factory) {
      callAdapterFactories.add(Objects.requireNonNull(factory, "factory == null"));
      return this;
    }

    //指定执行回调任务的Executor
    public Builder callbackExecutor(Executor executor) {
      this.callbackExecutor = Objects.requireNonNull(executor, "executor == null");
      return this;
    }

    public Retrofit build() {
      if (baseUrl == null) {
        throw new IllegalStateException("Base URL required.");
      }

      //设置默认OkHttpClient
      okhttp3.Call.Factory callFactory = this.callFactory;  
      if (callFactory == null) {
        callFactory = new OkHttpClient(); 
      }
     //android平台默认使用MainThreadExecutor,用于切换到主线程执行任务
      Executor callbackExecutor = this.callbackExecutor;
      if (callbackExecutor == null) {  
        callbackExecutor = platform.defaultCallbackExecutor();  
      }

      //添加平台默认CallAdapter.Factory到CallAdapterFactories
      List callAdapterFactories = new ArrayList<>(this.callAdapterFactories);  
      callAdapterFactories.addAll(platform.defaultCallAdapterFactories(callbackExecutor));

      //添加平台默认Converter.Factory到converterFactories 
      List converterFactories =
          new ArrayList<>(
              1 + this.converterFactories.size() + platform.defaultConverterFactoriesSize());
      converterFactories.add(new BuiltInConverters());
      converterFactories.addAll(this.converterFactories);
      converterFactories.addAll(platform.defaultConverterFactories());

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

如果未配置参数,build()方法会为我们提供大多数的默认配置,例如callAdapterFactories(创建网络请求适配器)、converterFactories(创建数据转换器)、callbackExecutor(执行回调任务)等待。

2. retrofit.create(ApiService::class.java).listRepos("octocat")

第一步:采取动态代理的方式创建请求接口的实现类

  public  T create(final Class service) {
    validateServiceInterface(service);
    return (T)
        Proxy.newProxyInstance(
            service.getClassLoader(),
            new Class[] {service},
            new InvocationHandler() {
              private final Platform platform = Platform.get();
              private final Object[] emptyArgs = new Object[0];

              @Override
              public @Nullable Object invoke(Object proxy, Method method, @Nullable 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);
                }
                args = args != null ? args : emptyArgs;
                //platform.isDefaultMethod(method)返回true表示方法是公共的非抽象实例方法
                return platform.isDefaultMethod(method)
                    ? platform.invokeDefaultMethod(method, service, proxy, args)
                    : loadServiceMethod(method).invoke(args);   //接口方法会执行到此处
              }
            });
  }

ApiService.kt是一个接口类,当我们调用接口内的方法时会执行代码loadServiceMethod(method).invoke(args),先分析loadServiceMethod(method)方法:

  ServiceMethod loadServiceMethod(Method method) {
    ServiceMethod result = serviceMethodCache.get(method);
    if (result != null) return result;

    synchronized (serviceMethodCache) {
      result = serviceMethodCache.get(method);
      if (result == null) {
        result = ServiceMethod.parseAnnotations(this, method);
        serviceMethodCache.put(method, result);
      }
    }
    return result;
  }

代码很简单,调用ServiceMethod.parseAnnotations(this, method)解析接口中的注解方法并封装成ServiceMethod。并且利用serviceMethodCache缓存解析结果,这样可以防止重复解析,使用缓存是因为解析的过程用到了比较耗费性能的反射机制。

abstract class ServiceMethod {
  static  ServiceMethod parseAnnotations(Retrofit retrofit, Method method) {
    //注释2.1:解析方法注解和参数注解,把注解中的网络请求参数封装到RequestFactory中
    RequestFactory requestFactory = RequestFactory.parseAnnotations(retrofit, method); 

    //注释2.2:保证方法返回类型不是Unresolvable和void.class
    Type returnType = method.getGenericReturnType();
    if (Utils.hasUnresolvableType(returnType)) {
      throw methodError(
          method,
          "Method return type must not include a type variable or wildcard: %s",
          returnType);
    }
    if (returnType == void.class) {
      throw methodError(method, "Service methods cannot return void.");
    }

    //注释2.3
    return HttpServiceMethod.parseAnnotations(retrofit, method, requestFactory);
  }

  abstract @Nullable T invoke(Object[] args);
}

注释2.1:RequestFactory.parseAnnotations(retrofit, method)解析注解信息,把信息封装到RequestFactory中
注释2.2:保证方法返回类型不是Unresolvable和void.class
注释2.3:调用HttpServiceMethod.parseAnnotations(retrofit, method, requestFactory)获取ServiceMethod

#HttpServiceMethod
//这里只贴出部分代码
  static  HttpServiceMethod parseAnnotations(
      Retrofit retrofit, Method method, RequestFactory requestFactory) {
    boolean isKotlinSuspendFunction = requestFactory.isKotlinSuspendFunction;
    boolean continuationWantsResponse = false;
    boolean continuationBodyNullable = false;

    Annotation[] annotations = method.getAnnotations();
    Type adapterType;  //方法返回值类型
    //isKotlinSuspendFunction默认为false,进入else语句获取adapterType 
    if (isKotlinSuspendFunction) {  
      ……
    } else {
      adapterType = method.getGenericReturnType(); 
    }
    //注释2.3.1:从callAdapterFactories列表中取出CallAdapter.Factory创建CallAdapter
    //我们可以使用Retrofit.Builder#addCallAdapterFactory(Factory)添加CallAdapter.Factory到列表callAdapterFactories
    //CallAdapter负责执行网络请求Call的适配工作
    CallAdapter callAdapter =
        createCallAdapter(retrofit, method, adapterType, annotations);  
    Type responseType = callAdapter.responseType();

    ……

    //注释2.3.2:从converterFactories列表中取出Converter.Factory创建Converter
    //我们可以使用Retrofit.Builder#addConverterFactory(Factory)添加Converter .Factory到converterFactories列表
    //Converter负责将服务端返回的数据转换成对象实例
    Converter responseConverter =
        createResponseConverter(retrofit, method, responseType);

    okhttp3.Call.Factory callFactory = retrofit.callFactory;
    //注释2.3.3:把requestFactory, callFactory, responseConverter, callAdapter封装进最终的HttpServiceMethod
    if (!isKotlinSuspendFunction) {
      return new CallAdapted<>(requestFactory, callFactory, responseConverter, callAdapter);
    } else if (continuationWantsResponse) {
      //noinspection unchecked Kotlin compiler guarantees ReturnT to be Object.
      return (HttpServiceMethod)
          new SuspendForResponse<>(
              requestFactory,
              callFactory,
              responseConverter,
              (CallAdapter>) callAdapter);
    } else {
      //noinspection unchecked Kotlin compiler guarantees ReturnT to be Object.
      return (HttpServiceMethod)
          new SuspendForBody<>(
              requestFactory,
              callFactory,
              responseConverter,
              (CallAdapter>) callAdapter,
              continuationBodyNullable);
    }
  }

注释2.3.1:从callAdapterFactories列表中取出CallAdapter.Factory创建CallAdapter,具体流程如下:

//HttpServiceMethod.java
  private static  CallAdapter createCallAdapter(
      Retrofit retrofit, Method method, Type returnType, Annotation[] annotations) {
    try {
      //noinspection unchecked
      return (CallAdapter) retrofit.callAdapter(returnType, annotations);
    } catch (RuntimeException e) { // Wide exception range because factories are user code.
      throw methodError(method, e, "Unable to create call adapter for %s", returnType);
    }
  }

调用retrofit.callAdapter(returnType, annotations)

#Retrofit.java
  public CallAdapter callAdapter(Type returnType, Annotation[] annotations) {
    return nextCallAdapter(null, returnType, annotations);
  }

  public CallAdapter nextCallAdapter(
      @Nullable CallAdapter.Factory skipPast, Type returnType, Annotation[] annotations) {
    Objects.requireNonNull(returnType, "returnType == null");
    Objects.requireNonNull(annotations, "annotations == null");

    int start = callAdapterFactories.indexOf(skipPast) + 1;
    //遍历callAdapterFactories列表获取CallAdapter.Factory来创建CallAdapter
    for (int i = start, count = callAdapterFactories.size(); i < count; i++) {  
      CallAdapter adapter = callAdapterFactories.get(i).get(returnType, annotations, this);
      if (adapter != null) {
        return adapter;
      }
    }

    //获取失败
  }

最终遍历callAdapterFactories列表获取CallAdapterFactory来创建我们需要的网络请求适配器CallAdapter,在构建Retrofit时已经添加Android平台默认的platform.defaultCallAdapterFactories到callAdapterFactories

//Retrofit.Builder#build()
//添加默认Call adapter.
List callAdapterFactories = new ArrayList<>(this.callAdapterFactories);
callAdapterFactories.addAll(platform.defaultCallAdapterFactories(callbackExecutor));

除了使用默认的CallAdapterFactory,我们也可以使用Retrofit.Builder#addCallAdapterFactory(Factory)主动添加CallAdapter.Factory到列表callAdapterFactories

CallAdapter主要负责执行网络请求Call的适配工作,注释2.3.2会详细分析

注释2.3.2:从converterFactories列表中取出Converter.Factory创建Converter,具体流程如下:

//HttpServiceMethod.java
  private static  Converter createResponseConverter(
      Retrofit retrofit, Method method, Type responseType) {
    Annotation[] annotations = method.getAnnotations();
    try {
      return retrofit.responseBodyConverter(responseType, annotations);
    } catch (RuntimeException e) { // Wide exception range because factories are user code.
      throw methodError(method, e, "Unable to create converter for %s", responseType);
    }
  }

调用retrofit.responseBodyConverter(responseType, annotations)

  public  Converter responseBodyConverter(Type type, Annotation[] annotations) {
    return nextResponseBodyConverter(null, type, annotations);
  }

  public  Converter nextResponseBodyConverter(
      @Nullable Converter.Factory skipPast, Type type, Annotation[] annotations) {
    Objects.requireNonNull(type, "type == null");
    Objects.requireNonNull(annotations, "annotations == null");

    int start = converterFactories.indexOf(skipPast) + 1;
    //遍历converterFactories列表获取Converter.Factory来创建Converter
    for (int i = start, count = converterFactories.size(); i < count; i++) {  
      Converter converter =
          converterFactories.get(i).responseBodyConverter(type, annotations, this);
      if (converter != null) {
        //noinspection unchecked
        return (Converter) converter;
      }
    }

    //获取失败
  }

最终遍历converterFactories列表获取Converter.Factory来创建我们需要的Converter,在构建Retrofit时已经添加Android平台默认的platform.defaultConverterFactories()到defaultConverterFactories

//Retrofit.Builder#build()
List converterFactories = new ArrayList<>(
     1 + this.converterFactories.size() + platform.defaultConverterFactoriesSize());
converterFactories.add(new BuiltInConverters());
converterFactories.addAll(this.converterFactories);
converterFactories.addAll(platform.defaultConverterFactories());

除了使用默认的ConverterFactory,我们也可以使用Retrofit.Builder#addConverterFactory(Factory)添加Converter .Factory到converterFactories列表;Converter负责将服务端返回的数据转换成对象实例

注释2.3.3:把requestFactory, callFactory, responseConverter, callAdapter封装进最终的HttpServiceMethod

如果未使用Kotlin的Suspend功能,注释2.3.3处会直接执行if语句,即创建一个CallAdapted,它继承自HttpServiceMethod,代码如下:

  static final class CallAdapted extends HttpServiceMethod {
    private final CallAdapter callAdapter;

    CallAdapted(
        RequestFactory requestFactory,
        okhttp3.Call.Factory callFactory,
        Converter responseConverter,
        CallAdapter callAdapter) {
      super(requestFactory, callFactory, responseConverter);
      this.callAdapter = callAdapter;
    }

    @Override
    protected ReturnT adapt(Call call, Object[] args) {
      return callAdapter.adapt(call);
    }
  }

CallAdapted主要是为了实现HttpServiceMethod的抽象方法ReturnT adapt(Call call, Object[] args),而具体工作交由callAdapter.adapt(call)方法执行。

我们再回到retrofit.create(ApiService::class.java)方法,重新贴一下代码:

  public  T create(final Class service) {
    validateServiceInterface(service);
    return (T)
        Proxy.newProxyInstance(
            service.getClassLoader(),
            new Class[] {service},
            new InvocationHandler() {
              private final Platform platform = Platform.get();
              private final Object[] emptyArgs = new Object[0];

              @Override
              public @Nullable Object invoke(Object proxy, Method method, @Nullable 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);
                }
                args = args != null ? args : emptyArgs;
                return platform.isDefaultMethod(method)
                    ? platform.invokeDefaultMethod(method, service, proxy, args)
                    : loadServiceMethod(method).invoke(args);
              }
            });
  }

第二步:当我们调用接口ApiService中的listRepos("octocat")方法,动态代理机制会调用InvocationHandler内的invoke(Object proxy, Method method, @Nullable Object[] args)方法,然后会执行loadServiceMethod(method).invoke(args)

通过前面的分析我们知道,loadServiceMethod(method)方法返回的是一个ServiceMethod,查看它的invoke()方法:

//ServiceMethod.java
abstract class ServiceMethod {
  static  ServiceMethod parseAnnotations(Retrofit retrofit, Method method) {
    RequestFactory requestFactory = RequestFactory.parseAnnotations(retrofit, method);

    Type returnType = method.getGenericReturnType();
    if (Utils.hasUnresolvableType(returnType)) {
      throw methodError(
          method,
          "Method return type must not include a type variable or wildcard: %s",
          returnType);
    }
    if (returnType == void.class) {
      throw methodError(method, "Service methods cannot return void.");
    }

    return HttpServiceMethod.parseAnnotations(retrofit, method, requestFactory);
  }

  abstract @Nullable T invoke(Object[] args);
}

invoke(Object[] args)方法在HttpServiceMethod中实现:

//HttpServiceMethod.java
  @Override
  final @Nullable ReturnT invoke(Object[] args) {
    Call call = new OkHttpCall<>(requestFactory, args, callFactory, responseConverter);
    return adapt(call, args);
  }

创建一个OkHttpCall对象作为adapt(call, args)方法的参数,前面已经分析过CallAdapted中实现了adapt(call, args)方法,call最终传递给callAdapter.adapt(call)方法适配出新call。(适配器模式)

如果没有手动指定callAdapter,默认使用DefaultCallAdapterFactory创建callAdapter:

//精简后的代码
final class DefaultCallAdapterFactory extends CallAdapter.Factory {
  private final @Nullable Executor callbackExecutor;

  DefaultCallAdapterFactory(@Nullable Executor callbackExecutor) {
    this.callbackExecutor = callbackExecutor;
  }

  @Override
  public @Nullable CallAdapter get(
      Type returnType, Annotation[] annotations, Retrofit retrofit) {

    final Executor executor =
        Utils.isAnnotationPresent(annotations, SkipCallbackExecutor.class)
            ? null
            : callbackExecutor;

    return new CallAdapter>() {
      @Override
      public Type responseType() {
        return responseType;
      }

      @Override
      public Call adapt(Call call) {
        return executor == null ? call : new ExecutorCallbackCall<>(executor, call);
      }
    };
  }

  static final class ExecutorCallbackCall implements Call {
    final Executor callbackExecutor;
    final Call delegate;

    ExecutorCallbackCall(Executor callbackExecutor, Call delegate) {
      this.callbackExecutor = callbackExecutor;
      this.delegate = delegate;
    }

    @Override
    public void enqueue(final Callback callback) {
      Objects.requireNonNull(callback, "callback == null");

      delegate.enqueue(
          new Callback() {
            @Override
            public void onResponse(Call call, final Response response) {
              callbackExecutor.execute(
                  () -> {
                    if (delegate.isCanceled()) {
                      // Emulate OkHttp's behavior of throwing/delivering an IOException on
                      // cancellation.
                      callback.onFailure(ExecutorCallbackCall.this, new IOException("Canceled"));
                    } else {
                      callback.onResponse(ExecutorCallbackCall.this, response);
                    }
                  });
            }

            @Override
            public void onFailure(Call call, final Throwable t) {
              callbackExecutor.execute(() -> callback.onFailure(ExecutorCallbackCall.this, t));
            }
          });
    }

  }
}
 
 

默认的网络请求适配器主要做了两件事:

  1. 在CallAdapter#adapt(Call call) 方法中将OkHttpCall适配成ExecutorCallbackCall来执行网络请求(适配器模式),真正的网络请求依然由OkHttpCall自己发起(代理模式)
  2. 请求完成后将Callback回调方法切换到callbackExecutor中执行,Retrofit提供的默认callbackExecutor负责将任务提交到主线程
  3. 3. OkHttpCall发起网络请求

    我们已经知道真正的网络请求由OkHttpCall发起,那还等什么快去看看吧

      @Override
      public void enqueue(final Callback callback) {
        Objects.requireNonNull(callback, "callback == null");
    
        okhttp3.Call call;
        Throwable failure;
    
        synchronized (this) {
          if (executed) throw new IllegalStateException("Already executed.");
          executed = true;
    
          call = rawCall;
          failure = creationFailure;
          if (call == null && failure == null) {
            try {
              call = rawCall = createRawCall();  //注释3.1: 使用OkHttpClient创建okhttp3.Call
            } catch (Throwable t) {
              throwIfFatal(t);
              failure = creationFailure = t;
            }
          }
        }
    
        if (failure != null) {
          callback.onFailure(this, failure);
          return;
        }
    
        if (canceled) {
          call.cancel();
        }
    
        //注释3.2:使用创建好的okhttp3.Call发起异步请求
        call.enqueue(
            new okhttp3.Callback() {
              @Override
              public void onResponse(okhttp3.Call call, okhttp3.Response rawResponse) {
                Response response;
                try {
                  response = parseResponse(rawResponse);  //注释3.3:解析服务端返回的数据
                } catch (Throwable e) {
                  throwIfFatal(e);
                  callFailure(e);
                  return;
                }
    
                try {
                  callback.onResponse(OkHttpCall.this, response); 
                } catch (Throwable t) {
                  throwIfFatal(t);
                  t.printStackTrace(); // TODO this is not great
                }
              }
    
              @Override
              public void onFailure(okhttp3.Call call, IOException e) {
                callFailure(e);
              }
    
              private void callFailure(Throwable e) {
                try {
                  callback.onFailure(OkHttpCall.this, e);
                } catch (Throwable t) {
                  throwIfFatal(t);
                  t.printStackTrace(); // TODO this is not great
                }
              }
            });
      }
    

    注释3.1: 使用OkHttpClient创建okhttp3.Call

      private okhttp3.Call createRawCall() throws IOException {
        okhttp3.Call call = callFactory.newCall(requestFactory.create(args));
        if (call == null) {
          throw new NullPointerException("Call.Factory returned null.");
        }
        return call;
      }
    

    注释3.2:使用创建好的okhttp3.Call发起异步请求

    注释3.3:处理服务端返回的数据

      Response parseResponse(okhttp3.Response rawResponse) throws IOException {
        ResponseBody rawBody = rawResponse.body();
    
        // Remove the body's source (the only stateful object) so we can pass the response along.
        rawResponse =
            rawResponse
                .newBuilder()
                .body(new NoContentResponseBody(rawBody.contentType(), rawBody.contentLength()))
                .build();
    
        //返回码处理
        int code = rawResponse.code();
        if (code < 200 || code >= 300) {  //网络请求出现异常
          try {
            // Buffer the entire body to avoid future I/O.
            ResponseBody bufferedBody = Utils.buffer(rawBody);
            return Response.error(bufferedBody, rawResponse);
          } finally {
            rawBody.close();
          }
        }
    
        if (code == 204 || code == 205) {  //返回Body为null的Response
          rawBody.close();
          return Response.success(null, rawResponse);  
        }
    
        ExceptionCatchingResponseBody catchingBody = new ExceptionCatchingResponseBody(rawBody);
        try {
          //responseConverter开始转换网络数据
          T body = responseConverter.convert(catchingBody);  
          return Response.success(body, rawResponse);
        } catch (RuntimeException e) {
          // If the underlying source threw an exception, propagate that rather than indicating it was
          // a runtime exception.
          catchingBody.throwIfCaught();
          throw e;
        }
      }
    

    执行responseConverter.convert(catchingBody)方法转换Response数据,那么responseConverter具体类型是什么呢?

    我们在初始化Retrofit时调用了Retrofit.Builder()#addConverterFactory(GsonConverterFactory.create())方法

    val retrofit = Retrofit.Builder()
            .baseUrl("https://api.github.com/")
            .client(okHttpClient)
            .addConverterFactory(GsonConverterFactory.create())  //添加Gson转换器
            .build()
    
    #Retrofit.java
        public Builder addConverterFactory(Converter.Factory factory) {
          converterFactories.add(Objects.requireNonNull(factory, "factory == null"));
          return this;
        }
    

    也就是将GsonConverterFactory添加到列表converterFactories,看一下GsonConverterFactory源码:

    public final class GsonConverterFactory extends Converter.Factory {
    
      public static GsonConverterFactory create() {
        return create(new Gson());
      }
    
      @SuppressWarnings("ConstantConditions") // Guarding public API nullability.
      public static GsonConverterFactory create(Gson gson) {
        if (gson == null) throw new NullPointerException("gson == null");
        return new GsonConverterFactory(gson);
      }
    
      private final Gson gson;
    
      private GsonConverterFactory(Gson gson) {
        this.gson = gson;
      }
    
      @Override
      public Converter responseBodyConverter(
          Type type, Annotation[] annotations, Retrofit retrofit) {
        TypeAdapter adapter = gson.getAdapter(TypeToken.get(type));
        return new GsonResponseBodyConverter<>(gson, adapter);
      }
    
      @Override
      public Converter requestBodyConverter(
          Type type,
          Annotation[] parameterAnnotations,
          Annotation[] methodAnnotations,
          Retrofit retrofit) {
        TypeAdapter adapter = gson.getAdapter(TypeToken.get(type));
        return new GsonRequestBodyConverter<>(gson, adapter);
      }
    }
    

    通过注释2.3.2可知,我们要寻找的responseConverter就是GsonResponseBodyConverter,重新回到注释3.3中的Response转换过程responseConverter.convert,本质上是执行GsonResponseBodyConverter.convert:

    final class GsonResponseBodyConverter implements Converter {
      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());
        try {
          T result = adapter.read(jsonReader);
          if (jsonReader.peek() != JsonToken.END_DOCUMENT) {
            throw new JsonIOException("JSON document was not fully consumed.");
          }
          return result;
        } finally {
          value.close();
        }
      }
    }
    

    convert(ResponseBody value)方法负责把ResponseBody转换成指定的数据类型

    到此为止,还剩最后一个任务:异步请求任务完成之后会以回调的方式通知发起方请求已经结束,为了方便将请求结果展示到UI上,需要把回调操作切换到主线程执行,这个任务由ExecutorCallbackCall负责完成

      static final class ExecutorCallbackCall implements Call {
        final Executor callbackExecutor;
        final Call delegate;
    
        ExecutorCallbackCall(Executor callbackExecutor, Call delegate) {
          this.callbackExecutor = callbackExecutor;
          this.delegate = delegate;
        }
    
        @Override
        public void enqueue(final Callback callback) {
          Objects.requireNonNull(callback, "callback == null");
    
          delegate.enqueue(
              new Callback() {
                @Override
                public void onResponse(Call call, final Response response) {
                  callbackExecutor.execute(
                      () -> {
                        if (delegate.isCanceled()) {
                          // Emulate OkHttp's behavior of throwing/delivering an IOException on
                          // cancellation.
                          callback.onFailure(ExecutorCallbackCall.this, new IOException("Canceled"));
                        } else {
                          callback.onResponse(ExecutorCallbackCall.this, response);
                        }
                      });
                }
    
                @Override
                public void onFailure(Call call, final Throwable t) {
                  callbackExecutor.execute(() -> callback.onFailure(ExecutorCallbackCall.this, t));
                }
              });
        }
    
        @Override
        public Response execute() throws IOException {
          return delegate.execute();
        }
        
        ……
      }
    

    具体方法是将callback.onXxxxx()回调方法丢到callbackExecutor执行,可以在Retrofit中使用方法callbackExecutor(Executor executor)配置callbackExecutor。

    如果未配置callbackExecutor,Retrofit会提供默认callbackExecutor,默认配置相关的实现依然是在Retrofit.Builder#build()方法中

    //Retrofit.Builder#build()
      Executor callbackExecutor = this.callbackExecutor;
      if (callbackExecutor == null) {
        callbackExecutor = platform.defaultCallbackExecutor();
      }
    
    //Android平台
      static final class Android extends Platform {
        Android() {
          super(Build.VERSION.SDK_INT >= 24);
        }
    
        @Override
        public Executor defaultCallbackExecutor() {
          return new MainThreadExecutor();
        }
    
        @Nullable
        @Override
        Object invokeDefaultMethod(
            Method method, Class declaringClass, Object object, Object... args) throws Throwable {
          if (Build.VERSION.SDK_INT < 26) {
            throw new UnsupportedOperationException(
                "Calling default methods on API 24 and 25 is not supported");
          }
          return super.invokeDefaultMethod(method, declaringClass, object, args);
        }
    
        static final class MainThreadExecutor implements Executor {
          private final Handler handler = new Handler(Looper.getMainLooper());
    
          @Override
          public void execute(Runnable r) {
            handler.post(r);
          }
        }
      }
    

    callbackExecutor默认是MainThreadExecutor,MainThreadExecutor负责将任务提交到主线程执行

    源码分析结束!

    Retrofit源码真是太牛逼了,本人水平有限,如有错误希望大家批评指正!


    参考资料

    • Carson带你学Android:手把手带你深入读懂Retrofit 2.0源码

    你可能感兴趣的:(Android网络请求库【Retrofit 2.9.0】基本用法与原理分析)