Retrofit源码解析

本文是基于Retrofit2.6.0源码的应用于分析。

Retrofit的应用
  • 定义一个网络请求接口
public interface GitHub {
  @GET("/repos/{owner}/{repo}/contributors")
  Call<List<Contributor>> contributors(@Path("owner") String owner, 
        @Path("repo") String repo);
}
  • 初始化一个Retrofit实例,采用构造者模式链式调用
Retrofit retrofit = new Retrofit.Builder()
    .baseUrl(API_URL)
    .addConverterFactory(GsonConverterFactory.create())
    .build();
  • 创建一个接口实现类Api:
//同步请求
GitHub github = retrofit.create(GitHub.class);
Call<List<Contributor>> call = github.contributors("square", "retrofit");
List<Contributor> contributors = call.execute().body();
//异步请求
call.enqueue(new Callback<List<Contributor>>() {
      @Override
      public void onResponse(Call<List<Contributor>> call, Response<List<Contributor>> response) {
      }
      @Override
      public void onFailure(Call<List<Contributor>> call, Throwable t) {
      }
    });

就这样我们完成了一次网络请求。
下面我们来看下源码中的具体实现。

Retrofit的源码实现
Retrofit retrofit = new Retrofit.Builder()
     .baseUrl(API_URL)
     .addConverterFactory(GsonConverterFactory.create())
     .build();
一. 先从Retrofit.Builder开始Builder调用了
public Builder() {
   this(Platform.get());
}

主要对Platform进行了实例化在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();
    } catch (ClassNotFoundException ignored) {
    }
    return new Platform();
  }

主要通过反射判断了Retrofit是在Java平台还是Android平台使用,本文是假设是在Android中使用,返回了一个Android继承Platform的实例并重构了部分方法。
.baseUrl(API_URL)没什么可说的主要是为Builder中的baseUrl赋值为一个HttpUrl;

.addConverterFactory(GsonConverterFactory.create())
  • 添加一个gson转换器工厂,GsonConverterFactory继承Converter.Factory,从字面翻译就可以理解转换工厂,提供了3个空实现返回的方法。再看GsonConverterFactory的实现
。。。省略主要看这两个方法
@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);
  }

这两个方法主要分别实现了ResponseBody转化为实体类和实体类转化为RequestBody。

  • 再看下最后的build()方法
public Retrofit build() {
      //判断url
      if (baseUrl == null) {
        throw new IllegalStateException("Base URL required.");
      }
      //未传入callFactory的话默认为OkHttpClient请求可以看出Retrofit框架可以
      //使用其他网络请求,它只是对网络请求进行了封装方便使用
      okhttp3.Call.Factory callFactory = this.callFactory;
      if (callFactory == null) {
        callFactory = new OkHttpClient();
      }
      //未传入线程池的话使用平台默认线程池Android平台默认为主线程
      Executor callbackExecutor = this.callbackExecutor;
      if (callbackExecutor == null) {
        callbackExecutor = platform.defaultCallbackExecutor();
      }

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

      // 转化工厂
      List<Converter.Factory> converterFactories = new ArrayList<>(
          1 + this.converterFactories.size() + platform.defaultConverterFactoriesSize());

     //将添加的配置都加入转化
      converterFactories.add(new BuiltInConverters());
      converterFactories.addAll(this.converterFactories);
      converterFactories.addAll(platform.defaultConverterFactories());
      //最后对Retrofit 进行实例化 并赋值初始化参数。
      return new Retrofit(callFactory, baseUrl, unmodifiableList(converterFactories),
          unmodifiableList(callAdapterFactories), callbackExecutor, validateEagerly);
    }
二、下面看下Retrofit中重要的一步,根据传入的接口返回一个代理实例:
GitHub github = retrofit.create(GitHub.class);

该方法调用了Retrofit中的create方法

  public <T> T create(final Class<T> service) {
    //先判断是否是接口
    Utils.validateServiceInterface(service);
    //默认为false
    if (validateEagerly) {
      eagerlyValidateMethods(service);
    }
    //返回一个动态代理
    return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class<?>[] { service },
        new InvocationHandler() {
          //当前为Android平台
          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 {
            // 判断是否为Object
            if (method.getDeclaringClass() == Object.class) {
              return method.invoke(this, args);
            }
            //sdk 24一下会直接返回flase 
            if (platform.isDefaultMethod(method)) {
              return platform.invokeDefaultMethod(method, service, proxy, args);
            }
            //最终调用
            return loadServiceMethod(method).invoke(args != null ? args : emptyArgs);
          }
        });
  }

至此Retrofit.create()只是生成了一个动态代理对象真正调用会是根据代理对象去调用其中方法:

Call<List<Contributor>> call = github.contributors("square", "retrofit");

根据代码分析会调用并返回loadServiceMethod(method).invoke(args != null ? args : emptyArgs);的值,主要从缓存中取出ServiceMethod,缓存中没有的话会调用ServiceMethod.parseAnnotations(this, 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.parseAnnotations(this, method)在方法又调用了Retrofit中的nextCallAdapter 与 nextResponseBodyConverter 得到了responseConverter与callFactory,并实例化一个SuspendForBody返回

 static <ResponseT, ReturnT> HttpServiceMethod<ResponseT, ReturnT> parseAnnotations(
      Retrofit retrofit, Method method, RequestFactory requestFactory) {
    boolean isKotlinSuspendFunction = requestFactory.isKotlinSuspendFunction;
    boolean continuationWantsResponse = false;
    boolean continuationBodyNullable = false;

    Annotation[] annotations = method.getAnnotations();
    Type adapterType;
    if (isKotlinSuspendFunction) {
      Type[] parameterTypes = method.getGenericParameterTypes();
      Type responseType = Utils.getParameterLowerBound(0,
          (ParameterizedType) parameterTypes[parameterTypes.length - 1]);
      if (getRawType(responseType) == Response.class && responseType instanceof ParameterizedType) {
        // Unwrap the actual body type from Response<T>.
        responseType = Utils.getParameterUpperBound(0, (ParameterizedType) responseType);
        continuationWantsResponse = true;
      } else {
        // TODO figure out if type is nullable or not
        // Metadata metadata = method.getDeclaringClass().getAnnotation(Metadata.class)
        // Find the entry for method
        // Determine if return type is nullable or not
      }

      adapterType = new Utils.ParameterizedTypeImpl(null, Call.class, responseType);
      annotations = SkipCallbackExecutorImpl.ensurePresent(annotations);
    } else {
      adapterType = method.getGenericReturnType();
    }

    CallAdapter<ResponseT, ReturnT> callAdapter =
        createCallAdapter(retrofit, method, adapterType, annotations);
    Type responseType = callAdapter.responseType();
    if (responseType == okhttp3.Response.class) {
      throw methodError(method, "'"
          + getRawType(responseType).getName()
          + "' is not a valid response body type. Did you mean ResponseBody?");
    }
    if (responseType == Response.class) {
      throw methodError(method, "Response must include generic type (e.g., Response<String>)");
    }
    // TODO support Unit for Kotlin?
    if (requestFactory.httpMethod.equals("HEAD") && !Void.class.equals(responseType)) {
      throw methodError(method, "HEAD method must use Void as response type.");
    }

    Converter<ResponseBody, ResponseT> responseConverter =
        createResponseConverter(retrofit, method, responseType);

    okhttp3.Call.Factory callFactory = retrofit.callFactory;
    if (!isKotlinSuspendFunction) {
      return new CallAdapted<>(requestFactory, callFactory, responseConverter, callAdapter);
    } else if (continuationWantsResponse) {
      //noinspection unchecked Kotlin compiler guarantees ReturnT to be Object.
      return (HttpServiceMethod<ResponseT, ReturnT>) new SuspendForResponse<>(requestFactory,
          callFactory, responseConverter, (CallAdapter<ResponseT, Call<ResponseT>>) callAdapter);
    } else {
      //noinspection unchecked Kotlin compiler guarantees ReturnT to be Object.
      return (HttpServiceMethod<ResponseT, ReturnT>) new SuspendForBody<>(requestFactory,
          callFactory, responseConverter, (CallAdapter<ResponseT, Call<ResponseT>>) callAdapter,
          continuationBodyNullable);
    }
  }
  • 我们再回到Retrofit中的Retrofit.create()方法,loadServiceMethod(method)从上面分析我们知道得到的是SuspendForBody,SuspendForBody继承了HttpServiceMethod,实际上是调用HttpServiceMethod的invoke()方法;invoke方法中实例了一个OkHttpCall对象并传入调用了SuspendForBody的adapt方法
  @Override final @Nullable ReturnT invoke(Object[] args) {
    Call<ResponseT> call = new OkHttpCall<>(requestFactory, args, callFactory, responseConverter);
    return adapt(call, args);
  }
  • SuspendForBody的adapt()方法,
    @Override protected Object adapt(Call<ResponseT> call, Object[] args) {
      call = callAdapter.adapt(call);

      //noinspection unchecked Checked by reflection inside RequestFactory.
      Continuation<ResponseT> continuation = (Continuation<ResponseT>) args[args.length - 1];
      return isNullable
          ? KotlinExtensions.awaitNullable(call, continuation)
          : KotlinExtensions.await(call, continuation);
    }

在未设置CallAdapter的情况下CallAdapter.adapt()最终调用的默认DefaultCallAdapterFactory.get()生成的CallAdapter,为ExecutorCallbackCall。至此我们得到了Call<List>。

三、接下来继续看应用层代码:
List<Contributor> contributors = call.execute().body();

从上面可知call是ExecutorCallbackCall类型的,call.execute()应该调用的是ExecutorCallbackCall中的方法,实际就是调用ExecutorCallbackCall实例化时传入的call,从上文的代码可知call为HttpServiceMethod.invoke()方法中生成的OkHttpCall,实际调用了它的execute()方法

    @Override public Response<T> execute() throws IOException {
      return delegate.execute();
    }
  • OkHttpCall的的execute()方法主要调用了createRawCall()根据之前构建的请求工厂,创建了okhttp3.Call这也是我们调用OkhttpClient进行请求的真实请求,之后调用了call.execute()发起请求并处理返回数据。
@Override public Response<T> execute() throws IOException {
    okhttp3.Call call;

    synchronized (this) {
      .....

      if (creationFailure != null) {
      ......
      call = rawCall;
      if (call == null) {
        try {
          //获取Okhttp请求RealCall
          call = rawCall = createRawCall();
        } catch (IOException | RuntimeException | Error e) {
          throwIfFatal(e); //  Do not assign a fatal error to creationFailure.
          creationFailure = e;
          throw e;
        }
      }
    }

    if (canceled) {
      call.cancel();
    }
    //发起请求并处理返回体
    return parseResponse(call.execute());
  }

这样我们Retrofit发起的一次同步请求就分析完成了,大体上了解了请求流程。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值