Retrofit 原理解析

Retrofit 是什么?

 * Retrofit adapts a Java interface to HTTP calls by using annotations on the declared methods to
 * define how requests are made. Create instances using {@linkplain Builder
 * the builder} and pass your interface to {@link #create} to generate an implementation.

Retrofit 是一个对于OkHttp 的增强附件,可以直接通过注解的方式,写网络请求方式(GET,POST),并且具备把返回结果转换成Java对象的扩展能力。

常见写法:

public interface TestService {

    @GET("api/weather/city/101030100/")
    Call<WeatherData> getWeather2();
    public class WeatherData{
        public String message;
        public String date;
    }

    @GET("api/weather/city/101030100/")
    Observable<WeatherData> getWeather4();
}

实现原理

1.首先利用Java动态代理技术,根据接口生成一个代理类。
retrofit2.Retrofit#create

  public <T> T create(final Class<T> 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 {
            return loadServiceMethod(method).invoke(args != null ? args : emptyArgs);
          }
        });
  }

2. 每次调用该代理对象的方法的时候,就会走到 invoke方法里。我们会在这个方法里解析注解,拿到请求参数,比如请求方法,参数等信息。
loadServiceMethod(method).invoke(args != null ? args : emptyArgs);
retrofit2.ServiceMethod#parseAnnotations

  static <T> ServiceMethod<T> 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);
  }

3.执行到loadServiceMethod(method).invoke(args != null ? args : emptyArgs);方法的地方:
retrofit2.HttpServiceMethod#invoke

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

4.然后在OkHttpCall里面,发起真正的网络请求
retrofit2.OkHttpCall#enqueue

  @Override public void enqueue(final Callback<T> callback) {
    call.enqueue(new okhttp3.Callback() {
      @Override public void onResponse(okhttp3.Call call, okhttp3.Response rawResponse) {
        Response<T> response;
        try {
          response = parseResponse(rawResponse);
        } 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
        }
      }
    });
  }

5.将网络返回的数据,根据Convert 转换成对应的接口返回的泛型类型。

如Call <WeatherData>,会把返回结果转成WeatherData 对象。

retrofit2.OkHttpCall#parseResponse

  Response<T> parseResponse(okhttp3.Response rawResponse) throws IOException {
    ResponseBody rawBody = rawResponse.body();

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

    ExceptionCatchingResponseBody catchingBody = new ExceptionCatchingResponseBody(rawBody);
    try {
      T body = responseConverter.convert(catchingBody);
      return Response.success(body, rawResponse);
    } catch (RuntimeException e) {
  
    }
  }

6.根据接口返回的实参类型,找到对应的实参转换工厂,生成返回值。
如果返回时Call<WeatherData> 则返回Call对象,如Observable<WeatherData> 则返回Observable对象。

如果是Call对象,则对应的Adapter 是:
retrofit2.DefaultCallAdapterFactory#get

            return new CallAdapter<Object, Call<?>>() {
                public Type responseType() {
                    return responseType;
                }

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

如果返回是Observable,那么是:
hu.akarnokd.rxjava3.retrofit.RxJava3CallAdapter#adapt

  @Override public Object adapt(Call<R> call) {
    Observable<Response<R>> responseObservable = isAsync
        ? new CallEnqueueObservable<>(call)
        : new CallExecuteObservable<>(call);

    Observable<?> observable;
    if (isResult) {
      observable = new ResultObservable<>(responseObservable);
    } else if (isBody) {
      observable = new BodyObservable<>(responseObservable);
    } else {
      observable = responseObservable;
    }
    return RxJavaPlugins.onAssembly(observable);
  }

最终RxJava将结果返回给调用的地方。

    @Override public void onNext(Response<R> response) {
      if (response.isSuccessful()) {
        observer.onNext(response.body());
      }
    }

反射获取返回类型:

method.getGenericReturnType()

这个方法是返回的一个全类型,比如对于 Observable<WeatherData> getWeather4(); 返回值是下面截图中的类型:

在这里插入图片描述

我们可以根据返回的总类型,拿到返回的泛型类型:

  ParameterizedType type
    Type[] types = type.getActualTypeArguments();

比如对于 Observable<WeatherData> getWeather4(); 我们可以先根据method.getGenericReturnType() 拿到整个的返回类型,然后调用 getActualTypeArguments 方法拿到泛型类型WeatherData

在这里插入图片描述

总结:

单一职责:

如果我需要一个功能,那么暴露接口出去,让别人实现,这就具备了可拓展性。比如说结果转换,返回结果的工厂。Retrofit只负责整个框架各个部门工作起来。

结果转换
      T body = responseConverter.convert(catchingBody);
      return Response.success(body, rawResponse);

CallAdapted 负责返回类型的转换

反射和注解

retrofit2.OkHttpCall 是真正的调用okhttp 的地方。
retrofit2.RequestFactory#create 负责生成请求的参数

Q:为什么要这样写:
  public <T> T create(final Class<T> service) { 
  而不是
    public <T> T create(final Class service) {
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章