Android开发Android开发经验谈Android技术知识

Retrofit2源码解析

2020-09-11  本文已影响0人  奔跑吧李博

Retrofit网络请求的功能实现是okhttp3,由okhttp3做真正的网络请求。Retrofit2框架和其他的用于网络请求的框架流程大体相同,Retrofit2优势在于,它使用了大量的设计模式将功能模块解耦,这样做的好处在于可以让流程更加清晰,可塑性更强。

请求过程伪代码:

        val retrofit = Retrofit.Builder()
                .baseUrl(SERVER_ADDRESS)
                .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
                .addConverterFactory(GsonConverterFactory.create())
                .client(mOkHttpClient)
                .build()
        var service = retrofit.create(MyService.class)
        service.getData()
流程图
请求流程
1、创建Retrofit实例;
2、创建网络请求接口和相关属性注解;
3、通过动态代理解析请求接口的注解,并生成网络请求对象;
4、通过CallAdapter进行平台适配;
5、通过OkHttpCall发送网络请求;
6、通过Converter数据转换适配器转换请求返回的数据;
7、通过线程切换执行器切换到主线程(仅限异步请求)。
源码分析

Retrofit部分代码:

public final class Retrofit {
  //网络请求缓存,如:请求方法、请求头、请求体,各种适配器等
  private final Map<Method, MethodHandler> methodHandlerCache = new LinkedHashMap<>();
  //okhttp工厂,真正发送交易的处理类
  private final okhttp3.Call.Factory callFactory;
  //请求url域名
  private final BaseUrl baseUrl;
  //数据转换器工厂集
  private final List<Converter.Factory> converterFactories;
  //网络请求适配器工厂集
  private final List<CallAdapter.Factory> adapterFactories;
  //异步请求结果线程切换执行器
  private final Executor callbackExecutor;
  //标志位、是否马上解析接口方法
  private final boolean validateEagerly;

  Retrofit(okhttp3.Call.Factory callFactory, BaseUrl baseUrl,
      List<Converter.Factory> converterFactories, List<CallAdapter.Factory> adapterFactories,
      Executor callbackExecutor, boolean validateEagerly) {
    this.callFactory = callFactory;
    this.baseUrl = baseUrl;
    this.converterFactories = converterFactories;
    this.adapterFactories = adapterFactories;
    this.callbackExecutor = callbackExecutor;
    this.validateEagerly = validateEagerly;
  }
}

Retrofit内部类Builder代码:
Retrofit通过建造者模式进行创建并设置属性,所以Builder类中与Retrofit类属性相同。

  public static final class Builder {
    private okhttp3.Call.Factory callFactory;
    private BaseUrl baseUrl;
    private List<Converter.Factory> converterFactories = new ArrayList<>();
    private List<CallAdapter.Factory> adapterFactories = new ArrayList<>();
    private Executor callbackExecutor;
    private boolean validateEagerly;
}

调用build方法:

    public Retrofit build() {
      //创建retrofit前对baseurl进行非空判断
      if (baseUrl == null) {
        throw new IllegalStateException("Base URL required.");
      }

      okhttp3.Call.Factory callFactory = this.callFactory;
      //创建okhttpClient,并赋予callFactory成员变量
      if (callFactory == null) {
        callFactory = new OkHttpClient();
      }

      // Make a defensive copy of the adapters and add the default Call adapter.
      List<CallAdapter.Factory> adapterFactories = new ArrayList<>(this.adapterFactories);
      adapterFactories.add(Platform.get().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的构造方法,创建一个Retrofit实例,通过建造者模式设置并初始化属性。

retrofit.create():

在创建好网络请求服务接口MyService类后,调用retrofit.create(MyService::class.java),这个方法是Retrofit的核心,内部采用动态代理,将咱们自定义的网络请求接口转换成一个ServiceMethod对象,ServiceMethod就是咱们Retrofit中的具体请求对象,里面封装了网络请求所必须的全部信息,包括请求方法、url、请求头、请求体等网络配置参数。

create方法代码:
  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, 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);
            }
            return loadMethodHandler(method).invoke(args);
          }
        });
  }

  private void eagerlyValidateMethods(Class<?> service) {
    Platform platform = Platform.get();
    for (Method method : service.getDeclaredMethods()) {
      if (!platform.isDefaultMethod(method)) {
// 将传入的ServiceMethod对象加入LinkedHashMap<Method, ServiceMethod>集合
        loadMethodHandler(method);
      }
    }
  }

如果validateEagerly提前验证的标志位为true,将会调用eagerlyValidateMethods(service)方法。传入service接口,通过反射获取内部方法。isDefaultMethod默认为false,因此loadServiceMethod(method)方法一定会走到。

isDefaultMethod方法代码:

  boolean isDefaultMethod(Method method) {
    return false;
  }

loadMethodHandler代码:

  private final Map<Method, MethodHandler> methodHandlerCache = new LinkedHashMap<>();

  MethodHandler loadMethodHandler(Method method) {
    MethodHandler handler;
    synchronized (methodHandlerCache) {
      handler = methodHandlerCache.get(method);
      // 即创建ServiceMethod对象前,先看serviceMethodCache有没有缓存之前创建过的网络请求实例
      // 若没缓存,则通过建造者模式创建 serviceMethod 对象
      if (handler == null) {
        handler = MethodHandler.create(this, method);
        methodHandlerCache.put(method, handler);
      }
    }
    return handler;
  }
创建OkHttpCall对象
OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);

OkHttpCall部分代码:

final class OkHttpCall<T> implements Call<T> {
        private okhttp3.Call rawCall;

  @Override public void enqueue(final Callback<T> callback) {
  
  }

  @Override public Response<T> execute() throws IOException {
   
  }
  

}

内部维护了一个okhttp3.Call rawCall的对象,接着看下面两个方法:enqueue()和execute(),可以看到内部调用的是rawCall的对应方法,也就是调用okhttp3.Call的enqueue()和execute()。

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.
   */
  public static GsonConverterFactory create(Gson gson) {
    return new GsonConverterFactory(gson);
  }

  private final Gson gson;

  private GsonConverterFactory(Gson gson) {
    if (gson == null) throw new NullPointerException("gson == null");
    this.gson = gson;
  }
}

GsonConverterFactory.creat()是创建了一个含有Gson对象实例的GsonConverterFactory,并返回给addConverterFactory()

Retrofit中addConverterFactory代码:

    public Builder addConverterFactory(Converter.Factory factory) {
      converterFactories.add(checkNotNull(factory, "factory == null"));
      return this;
    }

放入到数据转换器工厂converterFactories里,可用retrofit的默认Gson来解析,也可以自定义解析器。

CallAdapter

定义:网络请求执行器(Call)的适配器。

addCallAdapterFactory(RxJavaCallAdapterFactory.create())

把response封装成rxjava的Observeble,然后进行流式操作。

将response适配为Observable对象:

  static final class ResultCallAdapter implements CallAdapter<Observable<?>> {
    private final Type responseType;

    ResultCallAdapter(Type responseType) {
      this.responseType = responseType;
    }

    @Override public Type responseType() {
      return responseType;
    }

    @Override public <R> Observable<Result<R>> adapt(Call<R> call) {
      return Observable.create(new CallOnSubscribe<>(call)) //
          .map(new Func1<Response<R>, Result<R>>() {
            @Override public Result<R> call(Response<R> response) {
              return Result.response(response);
            }
          })
          .onErrorReturn(new Func1<Throwable, Result<R>>() {
            @Override public Result<R> call(Throwable throwable) {
              return Result.error(throwable);
            }
          });
    }
  }

总结

创建过程

动态创建网络请求接口的实例(代理模式 - 动态代理)
创建 serviceMethod 对象(建造者模式 & 单例模式(缓存机制))
对 serviceMethod 对象进行网络请求参数配置:通过解析网络请求接口方法的参数、返回值和注解类型,从Retrofit对象中获取对应的网络请求的url地址、网络请求执行器、网络请求适配器 & 数据转换器。(策略模式)
对 serviceMethod 对象加入线程切换的操作,便于接收数据后通过Handler从子线程切换到主线程从而对返回数据结果进行处理(装饰模式)
最终创建并返回一个OkHttpCall类型的网络请求对象

请求过程:

1.Retrofit 将 Http请求 抽象 成 Java接口
2.在接口里用 注解 描述和配置 网络请求参数
3.用动态代理 的方式,动态将网络请求接口的注解 解析 成HTTP请求
4.最后执行HTTP请求

参考:
Android:手把手带你 深入读懂 Retrofit 2.0 源码
Retrofit2源码分析:架构全面解析

上一篇下一篇

猜你喜欢

热点阅读