欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

Retrofit的原理剖析

程序员文章站 2022-06-16 12:58:59
关于RetrofitRetrofit是近来十分火热的一个网络请求开源库,Android开发者使用的网络请求开源库从最早的HttpClient与HttpURLConnection到2013年Google官方推出的Volley,接着就到了很火的OKHttp,最后才到了Retrofit。网络请求开源库的演变也正是移动互联网下用户对网络需求的真实写照。有哪个用户不想使用APP的时候网络加载速度更快,更省流量,更加安全呢?也就是基于用户的这些需求,才有了许多开源库的不断迭代,而Retrofit可以说正是当下最适合开...

1.关于Retrofit

Retrofit是近来十分火热的一个网络请求开源库,Android开发者使用的网络请求开源库从最早的HttpClient与HttpURLConnection到2013年Google官方推出的Volley,接着就到了很火的OKHttp,最后才到了Retrofit。网络请求开源库的演变也正是移动互联网下用户对网络需求的真实写照。有哪个用户不想使用APP的时候网络加载速度更快,更省流量,更加安全呢?也就是基于用户的这些需求,才有了许多开源库的不断迭代,而Retrofit可以说正是当下最适合开发者使用的网络请求开源库之一。
何出此言呢?首先它是由大名鼎鼎的square公司出品的,或许你不知道square公司,但你应该认识Jake Wharton,不过他最近已经到谷歌去了,倘若你连他都不知道,那你应该使用过他开发的这些开源库:OkHttp,picasso,butterknife,RxAndroid等等,可以说Retrofit是由一个十分厉害的公司开发和维护的,所以你大可以放心地在你的项目中使用。

2.应用场景

尽管Retrofit十分强大,但是他却不一定适合所有场景,正所谓术业有专攻,我们也不必大材小用,如果是一些频

  1. 繁但是访问量很小的网络请求,那么Volley就足以对付了,接下来我列举一下Retrofit普遍的使用场景。 服务器后台遵循RESTFUL API的设计风格。如果你对这种风格不熟悉,建议你看看阮一峰大神的这篇文章,或者向你的后台小伙伴请教一番。
  2. 项目中使用了RxJava。如果你的项目中使用了RxJava,那么使用Retrofit绝对会让你的开发效率翻倍。
  3. 项目中的网络数据请求量比较大。如果你的应用经常会有数据量比较大的网络请求,那么使用Retrofit也会很有效,因为Retrofit底层的实现是使用OKHttp,而OKHttp就是适用于这种场景的。
    如果你符合以上三种情况,当然是选择Retrofit啦!

3.基本使用

  1. 创建访问的接口
public interface ApiService {


    public static final String BASE_URL = "https://ss3.bdstatic.com";
    @Streaming
    @GET
    Observable<ResponseBody> executeDownload(@Header("Range") String range , @Url() String url);

}
  1. 创建Retrofit实例
        okHttpClient = new OkHttpClient.Builder()
                .connectTimeout(10, TimeUnit.SECONDS)
                .build();
        retrofit = new Retrofit.Builder()
                .addConverterFactory(GsonConverterFactory.create())
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                .baseUrl(baseUrl)
                .client(okHttpClient)
                .build();
  1. 通过动态代理获取访问接口的代理类对象
  apiService = retrofit.create(ApiService.class);
  1. 发起网络请求
  		 apiService.executeDownload("bytes=" + Long.toString(range) + totalLength, url)
                .subscribe(new Observer<ResponseBody>() {
                    @Override
                    public void onSubscribe(Disposable d) {

                    }

                    @Override
                    public void onNext(ResponseBody responseBody) {
                    }

                    @Override
                    public void onError(Throwable e) {
                    
                    }

                    @Override
                    public void onComplete() {

                    }
                });

4.源码解析

4.1先从builder模式创建Retrofit实例开始看起

  retrofit = new Retrofit.Builder()
                .addConverterFactory(GsonConverterFactory.create())  //添加一个转换器,将gson数据转换为bean类
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create()) // 添加一个适配器,与RxJava配合使用
                .baseUrl(baseUrl)
                .client(okHttpClient)
                .build();

显而易见,创建Retrofit实例使用了builder模式(建造者模式),接下来我们跟着源码来看看builder模式做了什么?首先看看builder( )这个方法:

public static final class Builder {
  public Builder() {
      this(Platform.get());
    }
  Builder(Platform platform) {
      this.platform = platform; //
      converterFactories.add(new BuiltInConverters());  //添加转换器,下面会专门讲解
    }
}

首先new Retrofit.Builder()其实是调用了Retrofit类里的Builder这个内部类的无参构造方法,构造方法里再次调用了Builder内部类中的有参构造方法,参数为Platform.get( );有参构造器根据传入的platform参数对platform赋值,且添加了转换器。我们再来看看Platform的get( )方法:

class Platform {
  private static final Platform PLATFORM = findPlatform();

  static Platform get() {
    return PLATFORM;
  }

  private static Platform findPlatform() {
    try {
      Class.forName("android.os.Build");
      if (Build.VERSION.SDK_INT != 0) {
        return new Android();  //安卓平台
      }
    } catch (ClassNotFoundException ignored) {
    }
    try {
      Class.forName("java.util.Optional");
      return new Java8();  //java8平台
    } catch (ClassNotFoundException ignored) {
    }
    return new Platform();
  }
}

可以看到,Retrofit支持多平台,包括Android与JAVA8,它会根据不同的平台设置不同的线程池。下面分析默认设置转换器等都会用到platform这个参数进行设置
先来看看到目前为止我们分析到哪里了
Retrofit的原理剖析

4.2接下来看一下baseUrl()方法。


public Class Buider { 

......

public Builder baseUrl(String baseUrl) {
  checkNotNull(baseUrl, "baseUrl == null");
  HttpUrl httpUrl = HttpUrl.parse(baseUrl);
  if (httpUrl == null) {
    throw new IllegalArgumentException("Illegal URL: " + baseUrl);
  }
  return baseUrl(httpUrl);
}

public Builder baseUrl(HttpUrl baseUrl) {
      checkNotNull(baseUrl, "baseUrl == null");
      List<String> pathSegments = baseUrl.pathSegments();
      if (!"".equals(pathSegments.get(pathSegments.size() - 1))) {
        throw new IllegalArgumentException("baseUrl must end in /: " + baseUrl);
      }
      this.baseUrl = baseUrl;
      return this;
    }

......
}

这里就是将url字符串解析成HttpUrl然后赋值给全局baseUrl 赋值

4.3接着是addConverterFactory()

public Class Builder
{
......
private final List<Converter.Factory> converterFactories = new ArrayList<>();
public Builder addConverterFactory(Converter.Factory factory) {
  converterFactories.add(checkNotNull(factory, "factory == null"));
  return this;
}
.......
}

这里的代码逻辑很简单,就是创建一个List集合(泛型为Converter.Factory类型的数组集合),通过addConverterFactory()方法将要添加的Converter.Factory放入集合中。
大家是不是还记得刚才在Builder()方法初始化的时候,有这样一行代码:

converterFactories.add(new BuiltInConverters());

可以看到,converterFactories在初始化的时候就已经添加了一个默认的Converter,那我们手动添加的这个GsonConverter是干什么用的呢?在看GsonConverterFactory 这个类之前,我们先来看看他的父类Converter.Factory:

public interface Converter<F, T> {


  T convert(F value) throws IOException;  //这里进行转换逻辑

 //转换器工厂
  abstract class Factory {
 
//将响应体转换成接口方法的泛型类型
    public @Nullable Converter<ResponseBody, ?> responseBodyConverter(Type type,
        Annotation[] annotations, Retrofit retrofit) {
      return null;
    }

//根据接口方法的参数类型以及注解,封装进RequestBody
    public @Nullable Converter<?, RequestBody> requestBodyConverter(Type type,
        Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) {
      return null;
    }


    public @Nullable Converter<?, String> stringConverter(Type type, Annotation[] annotations,
        Retrofit retrofit) {
      return null;
    }


    protected static Type getParameterUpperBound(int index, ParameterizedType type) {
      return Utils.getParameterUpperBound(index, type);
    }


    protected static Class<?> getRawType(Type type) {
      return Utils.getRawType(type);
    }
  }
}

我们在来看看GsonConverterFactory :

public final class GsonConverterFactory extends Converter.Factory {
  /**
   * Create an instance using a default {@link Gson} instance for conversion. Encoding to JSON and
   * decoding from JSON (when no charset is specified by a header) will use UTF-8.
   */
  public static GsonConverterFactory create() {
    return create(new Gson());
  }

  /**
   * Create an instance using {@code gson} for conversion. Encoding to JSON and
   * decoding from JSON (when no charset is specified by a header) will use UTF-8.
   */
  @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<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations,
      Retrofit retrofit) {
    TypeAdapter<?> adapter = gson.getAdapter(TypeToken.get(type));
    return new GsonResponseBodyConverter<>(gson, adapter);
  }

  @Override
  public Converter<?, RequestBody> requestBodyConverter(Type type,
      Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) {
    TypeAdapter<?> adapter = gson.getAdapter(TypeToken.get(type));
    return new GsonRequestBodyConverter<>(gson, adapter);
  }
}


-------------------------------------------------------------------------------

final class GsonResponseBodyConverter<T> implements Converter<ResponseBody, T> {
  private final Gson gson;
  private final TypeAdapter<T> adapter;

  GsonResponseBodyConverter(Gson gson, TypeAdapter<T> adapter) {
    this.gson = gson;
    this.adapter = adapter;
  }

  @Override public T convert(ResponseBody value) throws IOException {
    JsonReader jsonReader = gson.newJsonReader(value.charStream());
    try {
      return adapter.read(jsonReader);
    } finally {
      value.close();
    }
  }
}





我们先看responseBodyConverter和requestBodyConverter这个两个方法,其实光看这两个方法的名字,我们就可以知道,responseBodyConverter其实就是responseBody转换器,就是对Http响应回来的数据responseBody转换成你想要的数据类型;而requestBodyConverter就是将接口方法里的类型转换成RequestBody。相信小伙伴们对这两个方法的执行流程一目了然,只是不知道为什么能过转换而已,这里建议大家去看一下Gson源码。

上面分析了Converter的用途,但是小伙伴们可能只知道怎么设置Converter,却不知道具体在那里运用到了Converter的功能,我们再来一起看看源码,首先看一下下面的流程图:
Retrofit的原理剖析
很显然,Converter应该是ServiceMethod里的成员变量(不知道ServiceMethod里是什么东西的,可以先阅读一下第四节);我们先来看看具体那里与出现过ServiceMethod:


Class Retrofit {

.......
  public <T> T create(final Class<T> service) {
    Utils.validateServiceInterface(service);
    if (validateEagerly) {
      eagerlyValidateMethods(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, @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);
            }
            if (platform.isDefaultMethod(method)) {
              return platform.invokeDefaultMethod(method, service, proxy, args);
            }
            ServiceMethod<Object, Object> serviceMethod =
                (ServiceMethod<Object, Object>) loadServiceMethod(method);
            OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
            return serviceMethod.callAdapter.adapt(okHttpCall);
          }
        });
}

.......
  }

这段代码是Retrofit的精髓所在,利用动态代理,解析接口方法的注解和参数,通过Converter转换响应回来的数据类型,又可以根据接口方法返回值类型,利用Call适配器,可以实现即实现了网路请求又可以返回自己定义的接口方法返回的类型。其中关于接口方法的注解和参数的解析,以及Converter等等,最终都会封装到ServiceMethod里面,我们来看看ServiceMethod:

 public ServiceMethod build() {
      callAdapter = createCallAdapter();  // 这里是创建Call适配器地方,下一节解析
      responseType = callAdapter.responseType();  //其实就是返回接口方法的泛型类型
      if (responseType == Response.class || responseType == okhttp3.Response.class) 
      responseConverter = createResponseConverter();  // 这里创建了Converter

      for (Annotation annotation : methodAnnotations) {
        parseMethodAnnotation(annotation);
      }

      int parameterCount = parameterAnnotationsArray.length;
      parameterHandlers = new ParameterHandler<?>[parameterCount];
      for (int p = 0; p < parameterCount; p++) {
        Type parameterType = parameterTypes[p];
        Annotation[] parameterAnnotations = parameterAnnotationsArray[p];
        if (parameterAnnotations == null) {
          throw parameterError(p, "No Retrofit annotation found.");
        }
        parameterHandlers[p] = parseParameter(p, parameterType, parameterAnnotations);
      }
      return new ServiceMethod<>(this);
    }
	
    private Converter<ResponseBody, T> createResponseConverter() {
      Annotation[] annotations = method.getAnnotations();
      try {
        return retrofit.responseBodyConverter(responseType, annotations);
      } catch (RuntimeException e) { // Wide exception range because factories are user code.
        throw methodError(e, "Unable to create converter for %s", responseType);
      }
    }

这里调用了Retrofit的responseBodyConverter()方法,大家注意参数类型,这里跟上述将Converter的时候一样,传入了接口方法的泛型类型以及注解,进去对应Converter的匹配:

Class   Retrofit {

  public <T> Converter<ResponseBody, T> responseBodyConverter(Type type, Annotation[] annotations) {
    return nextResponseBodyConverter(null, type, annotations);
  }
  public <T> Converter<ResponseBody, T> nextResponseBodyConverter(
      @Nullable Converter.Factory skipPast, Type type, Annotation[] annotations) {
    checkNotNull(type, "type == null");
    checkNotNull(annotations, "annotations == null");

    int start = converterFactories.indexOf(skipPast) + 1;
    for (int i = start, count = converterFactories.size(); i < count; i++) {
      Converter<ResponseBody, ?> converter =
          converterFactories.get(i).responseBodyConverter(type, annotations, this);
      if (converter != null) {
        //noinspection unchecked
        return (Converter<ResponseBody, T>) converter;
      }
    }
}

到这里就知道了,其实就是根据参数获取对应集合里的转换器。
接着ServiceMethod会作为参数传入OkhttpCall()里:

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

翻看OkhttpCall里的源码,最终在这里实现了类型转换,将ResponeBody转换成接口方法的泛型类型:

  Response<T> parseResponse(okhttp3.Response rawResponse) throws IOException {
  .......

    ExceptionCatchingRequestBody catchingBody = new ExceptionCatchingRequestBody(rawBody);
    try {
      T body = serviceMethod.toResponse(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;
    }
  }

调用的是ServiceMethod的toResponse()方法:

  R toResponse(ResponseBody body) throws IOException {
    return responseConverter.convert(body);
  }

4.4接着看addCallAdapterFactory()方法

public final class Retrofit {

private final List<CallAdapter.Factory> adapterFactories = new ArrayList<>();
.......
public static final class Builder {
......

public Builder addCallAdapterFactory(CallAdapter.Factory factory) {
      adapterFactories.add(checkNotNull(factory, "factory == null"));
      return this;
}
......

}
......

显而易见,这是一个通过List集合维护的Call适配器,也就是说用户可以添加多个CallAdapter以适配Retrofit在不同平台或者框架上的使用;当然Retrofit也会有一个默认的设置,默认的是什么呢,我们接着来看build()这个方法:

public final class Retrofit {
.......
public static final class Builder {
........

    public Retrofit build() {
      if (baseUrl == null) {
        throw new IllegalStateException("Base URL required.");
      }
		//创建一个call,默认情况下使用okhttp作为网络请求器
      okhttp3.Call.Factory callFactory = this.callFactory;  //1
      if (callFactory == null) {
        callFactory = new OkHttpClient();
      }

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

      // Make a defensive copy of the adapters and add the default Call adapter.
      List<CallAdapter.Factory> adapterFactories = new ArrayList<>(this.adapterFactories);
      adapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor));  //2

      // Make a defensive copy of the converters.
      List<Converter.Factory> converterFactories = new ArrayList<>(this.converterFactories);

      return new Retrofit(callFactory, baseUrl, converterFactories, adapterFactories,
          callbackExecutor, validateEagerly);
    }
........

}
........

}

注释1中创建一个call,默认情况下使用okhttp作为网络请求器,在注释2处设置了一个默认的CallAdaptor,我们来看一下这个Adaptor:

class Platform {
......
  CallAdapter.Factory defaultCallAdapterFactory(@Nullable Executor callbackExecutor) {
    if (callbackExecutor != null) {
      return new ExecutorCallAdapterFactory(callbackExecutor);
    }
    return DefaultCallAdapterFactory.INSTANCE;
  }
  ......
}

如果我们没有设置执行器,如下所以:

   retrofit = new Retrofit.Builder()
            .addConverterFactory(GsonConverterFactory.create())
            .baseUrl(baseUrl)
            .client(okHttpClient)
            .callbackExecutor();
            .build();

那么他会调用ExecutorCallAdapterFactory()这个适配器工厂,根据源码,适配器工厂都继承了CallAdapter.Factory这个类,先来看看CallAdapter这个类:

public interface CallAdapter<R, T> {

  /**
 1. Returns the value type that this adapter uses when converting the HTTP response body to a Java
 2. object. For example, the response type for {@code Call<Repo>} is {@code Repo}. This type
 3. is used to prepare the {@code call} passed to {@code #adapt}.
 4. <p>
 5. Note: This is typically not the same type as the {@code returnType} provided to this call
 6. adapter's factory.
   */
  Type responseType();

  /**
 7. Returns an instance of {@code T} which delegates to {@code call}.
 8. <p>
 9. For example, given an instance for a hypothetical utility, {@code Async}, this instance would
 10. return a new {@code Async<R>} which invoked {@code call} when run.
 11. <pre><code>
 12. &#64;Override
 13. public &lt;R&gt; Async&lt;R&gt; adapt(final Call&lt;R&gt; call) {
 14.   return Async.create(new Callable&lt;Response&lt;R&gt;&gt;() {
 15.     &#64;Override
 16.     public Response&lt;R&gt; call() throws Exception {
 17.       return call.execute();
 18.     }
 19.   });
 20. }
 21. </code></pre>
   */
  T adapt(Call<R> call);

  /**
 22. Creates {@link CallAdapter} instances based on the return type of {@linkplain
 23. Retrofit#create(Class) the service interface} methods.
   */

}
  1. responseType():返回Http响应转换成java对象类型,例如接口方法返回的是Call,那么就是将响应内容封装进Repo这个java对象中,即指的是Call里的泛型类型。
  2. T adapt(Call call):传入Call对象,并且转换成泛型类型,这里是适配的关键方法,从这里也可以看出Retrofit给了我们很大的拓展*度,我们可以根据传入的call参数,做一些必要的操作

CallAdaptor接口里的内部类Factory:

public interface CallAdapter<R, T> {

......

   abstract class Factory {
    /**
     * Returns a call adapter for interface methods that return {@code returnType}, or null if it
     * cannot be handled by this factory.
     */

	//根据接口方法里的返回类型和方法参数,匹配合适的适配器
    public abstract @Nullable CallAdapter<?, ?> get(Type returnType, Annotation[] annotations,
        Retrofit retrofit);

    /**
     * Extract the upper bound of the generic parameter at {@code index} from {@code type}. For
     * example, index 1 of {@code Map<String, ? extends Runnable>} returns {@code Runnable}.
     */
	// 根据索引和通过反射获取方法中所有参数化类型来获取java对象
    protected static Type getParameterUpperBound(int index, ParameterizedType type) {
      return Utils.getParameterUpperBound(index, type);
    }

    /**
     * Extract the raw class type from {@code type}. For example, the type representing
     * {@code List<? extends Runnable>} returns {@code List.class}.
     */
     //获取Class字节码
    protected static Class<?> getRawType(Type type) {
      return Utils.getRawType(type);
    }
  }
  ......
 }

现在我们正式来看看它的具体实现,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) {
        return new ExecutorCallbackCall<>(callbackExecutor, call);
      }
    };
  }

  static final class ExecutorCallbackCall<T> implements Call<T> {
    final Executor callbackExecutor;
    final Call<T> delegate;

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

    @Override public void enqueue(final Callback<T> callback) {
      checkNotNull(callback, "callback == null");

      delegate.enqueue(new Callback<T>() {
        @Override public void onResponse(Call<T> call, final Response<T> response) {
          callbackExecutor.execute(new Runnable() {
            @Override public void run() {
              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<T> call, final Throwable t) {
          callbackExecutor.execute(new Runnable() {
            @Override public void run() {
              callback.onFailure(ExecutorCallbackCall.this, t);
            }
          });
        }
      });
    }

    @Override public boolean isExecuted() {
      return delegate.isExecuted();
    }

    @Override public Response<T> execute() throws IOException {
      return delegate.execute();
    }

    @Override public void cancel() {
      delegate.cancel();
    }

    @Override public boolean isCanceled() {
      return delegate.isCanceled();
    }

    @SuppressWarnings("CloneDoesntCallSuperClone") // Performing deep clone.
    @Override public Call<T> clone() {
      return new ExecutorCallbackCall<>(callbackExecutor, delegate.clone());
    }

    @Override public Request request() {
      return delegate.request();
    }
  }
}

直接使用delegate的enqueue方法,这个delegate实际就是OkHttpCall对象,里面走的就是okhttp的流程。最终有结果后会执行Callback的相应的回调方法,在这两个方法里面都用到了callbackExecutor这个任务对象来安排执行一个runnable对象,在runnable里面又回调了用户传入的Callback接口。那么callbackExecutor到底做了什么呢?
回顾上面,这个callbackExecutor是在ExecutorCallAapterFactory的构造函数里面传入的

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

这个构造函数在Platform这个类里面有三处调用:
Retrofit的原理剖析
因为我们是Android平台,所以直接看这个平台下的实现:



 static class Android extends Platform {
    @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);
      }
    }
  }

有两个方法,一个生成Executor,一个生成Factory,我们看生成的Executor对象其内部是创建了一个关联到主线程的handler,执行execute方法的时候,直接把runnable对象传递给handler加入到消息队列中。这里正是把网络请求的结果发送到UI线程中的执行逻辑,所以说在Android平台下,retrofit还是使用了handler来负责工作线程到主线程的切换工作的。

到这里,我们还只是知道了Android平台下executor的生成,那么它们是在哪里被调用的呢?
Retrofit的原理剖析
只有一处地方,就是在retrofit被构建的时候

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

      okhttp3.Call.Factory callFactory = this.callFactory;
      if (callFactory == null) {
        callFactory = new OkHttpClient();
      }

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

      // Make a defensive copy of the adapters and add the default Call adapter.
      List<CallAdapter.Factory> adapterFactories = new ArrayList<>(this.adapterFactories);
      adapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor));

      // Make a defensive copy of the converters.
      List<Converter.Factory> converterFactories = new ArrayList<>(this.converterFactories);

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

也就是在最开始的时候就已经创建好了各种资源。

retrofit提供给用户的接口非常简单便捷,但是其内部实现却很复杂甚至有点绕,不细心扣每一处细节的话,还真不一定能搞明白。

可以看到默认的callAdapter是ExecutorCallAdapterFactory。callAdapter其实也是运用了适配器模式,其实质就是网络请求器Call的适配器,而在Retrofit中Call就是指OKHttp,那么CallAdapter就是用来将OKHttp适配给不同的平台的,在Retrofit中提供了四种CallAdapter,分别如下:

  1. ExecutorCallAdapterFactory(默认使用)
  2. GuavaCallAdapterFactory
  3. Java8CallAdapterFactory
  4. RxJavaCallAdapterFactory

综上我们已经将使用Builder模式创建出来的Retrofit实例分析完毕了,我们只需要对相关的功能进行配置即可,Retrofit负责接收我们配置的功能然后进行对象的初始化,这个也就是Builder模式屏蔽掉创建对象的复杂过程的好处。现在我们再次用流程图来梳理一下刚才的思路。

Retrofit的原理剖析

4.5网络请求接口的创建

apiService = retrofit.create(ApiService.class);

	 apiService.executeDownload("bytes=" + Long.toString(range) + totalLength, url)
                .subscribe(new Observer<ResponseBody>() {
                    @Override
                    public void onSubscribe(Disposable d) {

                    }

                    @Override
                    public void onNext(ResponseBody responseBody) {
                    }

                    @Override
                    public void onError(Throwable e) {
                    
                    }

                    @Override
                    public void onComplete() {

                    }
                });

相信很多刚开始用Retrofit的小伙伴会奇怪,为什么我们写一个接口方法,然后调用retrofit.create()方法之后,就可以直接进行网络请求了呢?要想解惑,首先得对动态代理有所了解,如果你对动态代理还不是很清楚,请点击这里了解动态代理的原理,之后再接着往下看。

Public Class Retrofit{
......

  public <T> T create(final Class<T> service) {
    Utils.validateServiceInterface(service);
    if (validateEagerly) {
      eagerlyValidateMethods(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, @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);
            }
            if (platform.isDefaultMethod(method)) {
              return platform.invokeDefaultMethod(method, service, proxy, args);
            }
            
            ServiceMethod<Object, Object> serviceMethod =
                (ServiceMethod<Object, Object>) loadServiceMethod(method);  // 1 
            OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args); 
            return serviceMethod.callAdapter.adapt(okHttpCall);   //2
          }
        });
  }
......
}

我们重点来分析一下注释1和注释2的代码,先来看看loadServiceMethod(method)这个方法


Public Class Retrofit{
......
  ServiceMethod<?, ?> loadServiceMethod(Method method) {
    ServiceMethod<?, ?> result = serviceMethodCache.get(method);
    if (result != null) return result;

    synchronized (serviceMethodCache) {
      result = serviceMethodCache.get(method);  // 1
      if (result == null) {
        result = new ServiceMethod.Builder<>(this, method).build();  // 2
        serviceMethodCache.put(method, result);
      }
    }
    return result;
  }
......
  }

这里将接口方法作为参数,通过loadServiceMethod()方法的封装返回一个ServiceMethod对象;在注释1里,会现在缓存里查找,如果没有,才会在注释2处重新build一个出来,我们在来看一下ServiceMethod的 builder 内部类以及里面的build方法:

Class Builder{
.......
   Builder(Retrofit retrofit, Method method) {
      this.retrofit = retrofit;
      this.method = method;  //  获取接口中的方法名
      this.methodAnnotations = method.getAnnotations(); //获取方法里的注解
      this.parameterTypes = method.getGenericParameterTypes(); //获取方法里的参数类型 
      this.parameterAnnotationsArray = method.getParameterAnnotations();//获取接口方法里的注解内容 
    }


public ServiceMethod build() {
  callAdapter = createCallAdapter();   // 1
  responseType = callAdapter.responseType();
  if (responseType == Response.class || responseType == okhttp3.Response.class) {
    throw methodError("'"
        + Utils.getRawType(responseType).getName()
        + "' is not a valid response body type. Did you mean ResponseBody?");
  }
  responseConverter = createResponseConverter();

  for (Annotation annotation : methodAnnotations) {
    parseMethodAnnotation(annotation);  // 2
  }

  int parameterCount = parameterAnnotationsArray.length;
  parameterHandlers = new ParameterHandler<?>[parameterCount];
  for (int p = 0; p < parameterCount; p++) {
    Type parameterType = parameterTypes[p];
    if (Utils.hasUnresolvableType(parameterType)) {
      throw parameterError(p, "Parameter type must not include a type variable or wildcard: %s",
          parameterType);
    }

    Annotation[] parameterAnnotations = parameterAnnotationsArray[p];
    if (parameterAnnotations == null) {
      throw parameterError(p, "No Retrofit annotation found.");
    }

    parameterHandlers[p] = parseParameter(p, parameterType, parameterAnnotations);
  

  return new ServiceMethod<>(this);

}

}

这里的代码我删减了一点,其实里面还做了一些合法性校验,不符合就会抛出异常,我们先重点来看一下注释1的代码 callAdapter = createCallAdapter();

private CallAdapter<T, R> createCallAdapter() {
  Type returnType = method.getGenericReturnType();  //获取接口方法的返回类型
  if (Utils.hasUnresolvableType(returnType)) {
    throw methodError(
        "Method return type must not include a type variable or wildcard: %s", returnType);
  }
  if (returnType == void.class) {
    throw methodError("Service methods cannot return void.");
  }
  Annotation[] annotations = method.getAnnotations(); //获取接口方法的注解
  try {
    //noinspection unchecked
    // 根据方法的返回类型和注解,从retrofit实例中获取CallAapter对象。
    return (CallAdapter<T, R>) 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);
  }
}

我们看看Retrofit的callAdapter()方法:

Class Retrofit{

.......
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;
  for (int i = start, count = adapterFactories.size(); i < count; i++) {
    CallAdapter<?> adapter = adapterFactories.get(i).get(returnType, annotations, this);
    if (adapter != null) {
      return adapter;
    }
  }
}

这里主要是根据接口方法的返回值类型已经注解为参数在适配器集合中获取想应的适配器,再看下这个集合是在哪里赋值的:

private final List<CallAdapter.Factory> adapterFactories;
private final Executor callbackExecutor;
private final boolean validateEagerly;
 
Retrofit(okhttp3.Call.Factory callFactory, HttpUrl baseUrl,
    List<Converter.Factory> converterFactories, List<CallAdapter.Factory> adapterFactories,
    Executor callbackExecutor, boolean validateEagerly) {
  this.callFactory = callFactory;
  this.baseUrl = baseUrl;
  this.converterFactories = unmodifiableList(converterFactories); // Defensive copy at call site.
  this.adapterFactories = unmodifiableList(adapterFactories); // Defensive copy at call site.
  this.callbackExecutor = callbackExecutor;
  this.validateEagerly = validateEagerly;
}

查了一圈是在构造retrofit的时候,也就是说在使用Retrofit.Builder进行创建retrofit的时候赋值的。我们先暂时不去看这里。回到刚才的ServiceMethod.Builder的build方法内,

return new ServiceMethod<>(this);

最后返回一个ServiceMethod对象,此对象储存了解析了接口方法后的所有信息,还有一个CallAdapter对象。

ServiceMethod(Builder<T> builder) {
  this.callFactory = builder.retrofit.callFactory();
  this.callAdapter = builder.callAdapter;
  this.baseUrl = builder.retrofit.baseUrl();
  this.responseConverter = builder.responseConverter;
  this.httpMethod = builder.httpMethod;
  this.relativeUrl = builder.relativeUrl;
  this.headers = builder.headers;
  this.contentType = builder.contentType;
  this.hasBody = builder.hasBody;
  this.isFormEncoded = builder.isFormEncoded;
  this.isMultipart = builder.isMultipart;
  this.parameterHandlers = builder.parameterHandlers;
  }

最后,回到retrofit的create的InvocationHandler的invoke方法的最后一行:

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

调用了ServiceMethod的CallAapter对象的adapt方法生成了Call对象,也就是说当我们执行接口方法的时候其实是执行了invoke方法返回了一个Call对象。小伙伴们如果对CallAdapter适配过程还不太了解的话,可以返回去看看addCallAdapterFactory()方法里的流程。

本文地址:https://blog.csdn.net/qq_39431405/article/details/112387751