Retrofit源码解读

本篇文章使用的是Retrofit 2.3.0版本。Retrofit是基于okhttp的一个RESTful的HTTP网络请求框架的封装,内部的网络请求还是由okhttp完成的,对OkHttp不了解的可以看看:

OkHttp3源码解读(一)同步与异步

 OkHttp3源码解读(二)请求响应与拦截器

Retrofit封装了接口层的请求参数以及请求结果的解析及转换(支持Gson、XML、JSON、protobuf等)等。

本文目的:

①retrofit是怎么将方法及其参数转化为请求的?

②retrofit.create得到的类是什么?

我们以Retrofit基本的用法作为入口:

//创建retrofit对象
Retrofit retrofit = new Retrofit.Builder()
        //使用自定义的mGsonConverterFactory
        .addConverterFactory(GsonConverterFactory.create())
        .baseUrl("http://apis.baidu.com/txapi/")
        .build();
// 实例化我们的mApi对象
mApi = retrofit.create(APi.class); 

// 调用我们的响应的方法
Call<News> news = mApi.getNews(number, page);
news.enqueue(new Callback<News>() {
    @Override
    public void onResponse(Call<News> call, Response<News> response) {
        News body = response.body();
        Logger.i("onResponse:   ="+body.toString());
    }

    @Override
    public void onFailure(Call<News> call, Throwable t) {
        Logger.i("onResponse:   ="+t.getMessage());

    }
});

可以看到Retrofit类使用建造者模式(Build模式)初始化对象,我们先看一下Retrofit类:

public final class Retrofit {
  private final Map<Method, ServiceMethod<?, ?>> serviceMethodCache = new ConcurrentHashMap<>();

  final okhttp3.Call.Factory callFactory;
  final HttpUrl baseUrl;
  final List<Converter.Factory> converterFactories;
  final List<CallAdapter.Factory> adapterFactories;
  final @Nullable Executor callbackExecutor;
  final boolean validateEagerly;

  Retrofit(okhttp3.Call.Factory callFactory, HttpUrl baseUrl,
      List<Converter.Factory> converterFactories, List<CallAdapter.Factory> adapterFactories,
      @Nullable 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;
  }
}

ServiceMethod:网络请求配置对象,包含相关的配置(如请求头、请求方法、请求的参数等)

okhttp3.Call.Factory:网络请求的工厂,生成网络请求的Call,默认是OkHttpClient,这个应该不陌生,学过OkHttpClient的都知道OkHttpClient用来配置缓存、拦截器等。

Converter.Factory:生成数据装换器,比如:将请求结果转化为JSON、XML等,这里我们用GsonConverterFactory做例子

CallAdapter.Factory:生成网络请求适配器,将网络请求执行器OkHttpCall转换成适合不同平台来调用的网络请求执行器。Retrofit支持Android、RxJava、java8、Guava等平台,所以Retrofit提供了四中CallAdapterFactory、ExecutorCallAdapterFactory、GuavaCallAdapterFactory、Java8CallAdapterFactory。默认情况下是ExecutorCallAdapterFactory,如果使用RxJava2CallAdapter,请求会被转换为Observable对象。

callbackExecutor:回调方法执行器,将请求结果使用Handler传回到主线程。

在下面的分析中我们将会看到这些类的使用。

接着我们看一下new Retrofit.Builder()

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

Platform.get()调用findPlatform方法:

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();
    } catch (ClassNotFoundException ignored) {
    }
    return new Platform();
  }

Class.forName()是要求JVM查找并加载某个类并执行该类的静态代码段。如果是Android平台则返回一个Android对象,Android对象也是继承Platform:

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);
      }
    }
  }

Platform的主要作用是当没有指定特定的回调方法执行器CallbackExecutor和网络请求适配器CallAdapterFactory时用来获取一个默认的CallbackExecutor和CallAdapterFactory,分别是MainThreadExecutor(将Runnable从子线程切换到主线程执行)和ExecutorCallAdapterFactory(这个之后会用到)

Retrofit的配置过程我们就不看了,直接看Builder的build方法:

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);
    }

可以看到默认的callFactory是OkHttpClient,默认的callbackExecutor从platform获取,添加一个默认的CallAdapterFactory,调用Retrofit的构造函数,传入参数并返回Retrofit对象。

Retrofit构造完成后,接着看我们的代码:

​
//创建retrofit对象
Retrofit retrofit = new Retrofit.Builder()
        //使用自定义的mGsonConverterFactory
        .addConverterFactory(GsonConverterFactory.create())
        .baseUrl("http://apis.baidu.com/txapi/")
        .build();
// 实例化我们的mApi对象
mApi = retrofit.create(APi.class); 

​

调用Retrofit的create方法,传入我们的接口类:

public <T> T create(final Class<T> service) {
    Utils.validateServiceInterface(service);//验证接口是否有效
    if (validateEagerly) {
      //用接口的每个方法生成一个ServiceMethod并放入Map类对象serviceMethodCache中
      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);
          }
        });
  }

可以看到先调用validateServiceInterface验证接口是否有效,然后调用eagerlyValidateMethods方法:

private void eagerlyValidateMethods(Class<?> service) {
    Platform platform = Platform.get();
    for (Method method : service.getDeclaredMethods()) {//遍历每个方法
      if (!platform.isDefaultMethod(method)) {//排除默认方法
        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) {
        //创建ServiceMethod对象
        result = new ServiceMethod.Builder<>(this, method).build();
        serviceMethodCache.put(method, result);
      }
    }
    return result;
  }

遍历接口的每个方法,为每个方法创建一个ServiceMethod对象,并放入serviceMethodCache中。我们看看ServiceMethod:

final class ServiceMethod<R, T> {
  // Upper and lower characters, digits, underscores, and hyphens, starting with a character.
  static final String PARAM = "[a-zA-Z][a-zA-Z0-9_-]*";
  static final Pattern PARAM_URL_REGEX = Pattern.compile("\\{(" + PARAM + ")\\}");
  static final Pattern PARAM_NAME_REGEX = Pattern.compile(PARAM);

  final okhttp3.Call.Factory callFactory;
  final CallAdapter<R, T> callAdapter;

  private final HttpUrl baseUrl;
  private final Converter<ResponseBody, R> responseConverter;
  private final String httpMethod;
  private final String relativeUrl;
  private final Headers headers;
  private final MediaType contentType;
  private final boolean hasBody;
  private final boolean isFormEncoded;
  private final boolean isMultipart;
  private final ParameterHandler<?>[] parameterHandlers;

  ...
}

可以看到这个类包含了url、请求结果转换器、请求方法、请求头、注解等信息。我们看一下它的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();
      responseType = callAdapter.responseType();
      ...
      responseConverter = createResponseConverter();

      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];
        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);
    }

构造方法获取方法的注解、参数、参数的注解。

在build方法中,调用createCallAdapter方法,createCallAdapter方法调用retrofit的callAdapter方法获取CallAdapter:

public CallAdapter<?, ?> callAdapter(Type returnType, Annotation[] annotations) {
    return nextCallAdapter(null, returnType, annotations);
  }

  public CallAdapter<?, ?> nextCallAdapter(@Nullable 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;
      }
    }
    ...
  }

这里的参数returnType是我们的接口方法的返回类型,比如,Call<ResponseBody>。遍历retrofit中adapterFactories列表获取CallAdapter.Factory并调用get方法生成一个CallAdapter并返回,这里我们以默认的ExecutorCallAdapterFactory为例:

@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);
      }
    };
  }

这里调用Utils的getCallResponseType方法获得方法返回类型中参数化类型的Type:

static Type getCallResponseType(Type returnType) {
    if (!(returnType instanceof ParameterizedType)) {
      throw new IllegalArgumentException(
          "Call return type must be parameterized as Call<Foo> or Call<? extends Foo>");
    }
    return getParameterUpperBound(0, (ParameterizedType) returnType);
  }

比如:如果method的返回类型为Call<Foo>或者Call<? extends Foo>,则这个方法返回Foo类的Type。并使CallAdapter的responseType返回该类型。

我们回到ServiceMethod.Builder的build方法,获取CallAdapter后,调用callAdapter的responseType获取返回类型中参数化类型的Type,然后调用createResponseConverter方法,createResponseConverter方法又调用Retrofit的responseBodyConverter方法,通过converterFactories获取一个Converter.Factory,并调用responseBodyConverter获取一个Converter对象,过程和获取CallAdapter时差不多,这里就赘述了。

回到ServiceMethod.Builder的build方法,

public ServiceMethod build() {
      callAdapter = createCallAdapter();
      responseType = callAdapter.responseType();

      responseConverter = createResponseConverter();
      //解析方法注解
      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];
        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);
    }

调用parseMethodAnnotation解析方法的注解,获得httpMethod等信息,然后再解析参数的注解,调用parseParameter,为每一个参数生成一个ParameterHandler对象,存放于ParameterHandler数组中。总结:ServiceMethod解析并存放接口方法的网络请求信息。

接下来回到Retrofit的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, @Nullable Object[] args)
              throws Throwable {
            ...
            ServiceMethod<Object, Object> serviceMethod =
                (ServiceMethod<Object, Object>) loadServiceMethod(method);
            OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
            return serviceMethod.callAdapter.adapt(okHttpCall);
          }
        });
  }

create方法返回我们接口的代理对象,当我们该代理对象的方法时,就会调用它的invoke方法,先获取方法的ServiceMethod对象,然后构造一个OkHttpCall对象,调用ServiceMethod的callAdapter对象的adapter方法,这里我们以默认的CallAdapter为例,也就是ExecutorCallAdapterFactory生成的CallAdapter:

@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);
      }
    };
  }

可以看到它的adapt方法返回一个ExecutorCallbackCall对象(继承自Call),内存存放我们传入的OkHttpCall对象。当我们调用该Call对象的execute方法执行请求时,ExecutorCallbackCall对象内部还是调用OkHttpCall对象的execute方法:

@Override public Response<T> execute() throws IOException {
    okhttp3.Call call;

    synchronized (this) {
      if (executed) throw new IllegalStateException("Already executed.");
      executed = true;
      ...
      call = rawCall;
      if (call == null) {
        try {
          call = rawCall = createRawCall();
        } catch (IOException | RuntimeException e) {
          creationFailure = e;
          throw e;
        }
      }
    }

    if (canceled) {
      call.cancel();
    }

    return parseResponse(call.execute());
  }

createRawCall方法通过serviceMethod中请求的信息构造一个请求并返回。然后执行该请求的execute方法获取响应,获取响应的流程就是通过Okhttp来获取的。得到响应后,利用Converter解析响应得到想要的格式。

 

总结:Retrofit的分析就到这里,主要通过反射获取注解的信息,构造请求,还有Converter和CallAdapter的作用,CallAdapter在代理的invoke方法返回时起作用,将返回类型转换为特定的类型(如Call<R>、或者Rxjava的Observer),Converter在获取响应之后将结果转换为特定的格式(如ResponseBody等)。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值