源码解析Retrofit

1. Retrofit的创建过程

  • 当我们使用Retrofit请求网络时,首先要写请求网络接口。
public interface IpService{
    ...
}
  • 接着,我们要调用如下代码来创建Retrofit
Retrofit retrofit = new Retrofit.Builder()
        .baseUrl(url)
        .addConverterFactory(GsonConverterFactory.create())
        .build;
  • Retrofit是通过建造者模式来创建的
  • 让我们来看看Builder()方法做了什么
  1. Retrofit # Builder()
  • Builder是Retrofit的静态内部类,Builder()是内部类的构造方法
public Builder() {
  this(Platform.get());
}
  1. 查看Platform的get方法
  • get方法返回PLATFORM,调用findPlatform
private static final Platform PLATFORM = findPlatform();

static Platform get() {
  return PLATFORM;
}
  1. Platform # findPlatform
  • 根据不同的运行平台来提供不同的线程池
private static Platform findPlatform() {
  try {
    //要求JVm查找并加载指定类
    Class.forName("android.os.Build");
    if (Build.VERSION.SDK_INT != 0) {
      return new Android();
    }
  } catch (ClassNotFoundException ignored) {
  }
  return new Platform(true);
}
  1. 接下来查看Retrofit.Builder的build方法
  • Builder类和Retrofit类的成员变量是对应的,Retrofit的成员变量通过Builder类配置请添加图片描述
  • 前面的例子中使用addConverterFactory(GsonConverterFactory.create()),设置了返回的数据支持转换为Gson对象,并最终会返回配置好的Retrofit类。
public Retrofit build() {
  //1.必须指定baseUrl
  if (baseUrl == null) {
    throw new IllegalStateException("Base URL required.");
  }

  //2.callFactory默认为this.callFactroy
  okhttp3.Call.Factory callFactory = this.callFactory;
  if (callFactory == null) {
    //3.
    callFactory = new OkHttpClient();
  }

  //4.callbackExecutor用来回调传递给UI线程
  Executor callbackExecutor = this.callbackExecutor;
  if (callbackExecutor == null) {
    callbackExecutor = platform.defaultCallbackExecutor();
  }

  //5.CallAdapterFactories主要用来存储对Call进行转化的对象
  // Make a defensive copy of the adapters and add the default Call adapter.
  List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>(this.callAdapterFactories);
  callAdapterFactories.addAll(platform.defaultCallAdapterFactories(callbackExecutor));

  // 6.converterFactories主要用来存储转化数据对象
  List<Converter.Factory> converterFactories = new ArrayList<>(
      1 + this.converterFactories.size() + platform.defaultConverterFactoriesSize());

  // Add the built-in converter factory first. This prevents overriding its behavior but also
  // ensures correct behavior when using converters that consume all types.
  converterFactories.add(new BuiltInConverters());
  converterFactories.addAll(this.converterFactories);
  converterFactories.addAll(platform.defaultConverterFactories());

  return new Retrofit(callFactory, baseUrl, unmodifiableList(converterFactories),
      unmodifiableList(callAdapterFactories), callbackExecutor, validateEagerly);
}
public Builder callFactory(okhttp3.Call.Factory factory) {
  this.callFactory = Objects.requireNonNull(factory, "factory == null");
  return this;
}
public Builder addConverterFactory(Converter.Factory factory) {
  //converterFactories用来存储转化数据对象
  converterFactories.add(Objects.requireNonNull(factory, "factory == null"));
  return this;
}

2. Call的创建过程

  • 下面我们创建Retrofit实例并调用如下代码来生成接口的动态代理对象。
  • 之后调用该接口的getIpMsg方法得到Call对象
IpService ipService  = retrofit.create(IpService.class);
  1. 接下来看Retrofit的create方法
  • validateServiceInterfacezhe
  • 可以看到create方法返回了一个Proxy.newProxyInstance动态代理对象
  • 将代理类的实现交给InvocationHandler类来具体实现
  • 当我们调用IpService的getIpMsg方法时,最终会调用InvocationHandler的invoke方法
  • invoke方法有三个参数:代理对象、调用的方法、方法的参数
  • 然后会调用loadServiceMethod方法,这个方法中的参数method就是我们定义的getIpMsg方法
    在这里插入图片描述
public <T> T create(final Class<T> service) {
  validateServiceInterface(service);
  //newProxyInstance是个方法,内部有三个参数
  return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class<?>[] { service },
      new InvocationHandler() {
        private final Platform platform = Platform.get();
        private final Object[] emptyArgs = new Object[0];

        //当我们调用IpService的getIpMsg方法时,最终会调用InvocationHandler的invoke方法
        @Override public @Nullable 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);
          }
          return loadServiceMethod(method).invoke(args != null ? args : emptyArgs);
        }
      });
}
  1. Retrofit # loadServiceMethod
  • 先通过serviceMethodCache来查询传入的方法有没有缓存
  • 如果有就用缓存的ServiceMethod,没有的话就创建一个,并加入到serviceMethodCache中缓存起来。
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;
}
  1. 下面查看如何构建ServiceMethod (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);
}

2.1 调用RequestFactroy的parseAnnotations方法

  • 这个方法可以解析网络请求接口的注解
static RequestFactory parseAnnotations(Retrofit retrofit, Method method) {
  return new Builder(retrofit, method).build();
}
...
Builder(Retrofit retrofit, Method method) {
  this.retrofit = retrofit;
  this.method = method;
  this.methodAnnotations = method.getAnnotations();
  this.parameterTypes = method.getGenericParameterTypes();
  this.parameterAnnotationsArray = method.getParameterAnnotations();
}
...

2.2 调用HttpServiceMethod的parseAnnotations

  • 这个方法获取了对应的网络请求适配器(CallAdapter)、数据转换器(Converter)与网络请求器工厂(okhttp3.Call.Factory)
  • 最后通过这些来创建HttpServiceMethod对象进行返回请添加图片描述
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();
  }
  
  //1.调用了createCallAdapter方法
  CallAdapter<ResponseT, ReturnT> callAdapter =
      createCallAdapter(retrofit, method, adapterType, annotations);
  //2.返回数据的真实类型
  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.");
  }

  //3.调用createResponseConverter方法来遍历converterFactories列表中存储的Converter.Factory
  //并返回一个合适的Converter用来转换对象
  Converter<ResponseBody, ResponseT> responseConverter =
      createResponseConverter(retrofit, method, responseType);

  okhttp3.Call.Factory callFactory = retrofit.callFactory;
  if (!isKotlinSuspendFunction) {
  //CallAdapted类继承自HttpServiceMethod类,并实现了adapt抽象方法
  //HttpServiceMethod继承自ServiceMethod
  //Retrofit的create方法中的loadServiceMethod方法实际上返回HttpServiceMethod对象。
    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);
  }
}

1.注释1的后续解释

  1. 这是Retrofit的build方法内的部分代码
  2. 它的作用是存储对Call进行转化的对象。请添加图片描述
  List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>(this.callAdapterFactories);
  callAdapterFactories.addAll(platform.defaultCallAdapterFactories(callbackExecutor));
  • 来看ExecutorCallAdapterFactory的get方法
  • get方法会得到一个CallAdapter对象,CallAdapter的responseType方法会返回数据的真实类型
  • 比如:传入的是Call,responseType方法就会返回IpModel
  • adapt方法会将call的回调返回转发至UI线程
@Override public @Nullable CallAdapter<?, ?> get(
    Type returnType, Annotation[] annotations, Retrofit retrofit) {
  if (getRawType(returnType) != Call.class) {
    return null;
  }
  if (!(returnType instanceof ParameterizedType)) {
    throw new IllegalArgumentException(
        "Call return type must be parameterized as Call<Foo> or Call<? extends Foo>");
  }
  final Type responseType = Utils.getParameterUpperBound(0, (ParameterizedType) returnType);

  final Executor executor = Utils.isAnnotationPresent(annotations, SkipCallbackExecutor.class)
      ? null
      : callbackExecutor;

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

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

在这里插入图片描述

2.3 Retrofit的create方法最后调用了invoke方法

  1. Retrofit # create
return loadServiceMethod(method).invoke(args != null ? args : emptyArgs);
  1. ServiceMethod # invoke
abstract @Nullable T invoke(Object[] args);
  1. HttpServiceMethod # invoke
  • HttpServiceMethod继承了ServiceMethod
@Override final @Nullable ReturnT invoke(Object[] args) {
  Call<ResponseT> call = new OkHttpCall<>(requestFactory, args, callFactory, responseConverter);
  return adapt(call, args);
}
  1. HttpServiceMethod # adapt
  • 抽象类HttpServiceMethod 的 abstract adapt()
protected abstract @Nullable ReturnT adapt(Call<ResponseT> call, Object[] args);
  1. CallAdapter
  • CallAdapted继承了HttpServiceMethod
static final class CallAdapted<ResponseT, ReturnT> extends HttpServiceMethod<ResponseT, ReturnT> {
  private final CallAdapter<ResponseT, ReturnT> callAdapter;

  CallAdapted(RequestFactory requestFactory, okhttp3.Call.Factory callFactory,
      Converter<ResponseBody, ResponseT> responseConverter,
      CallAdapter<ResponseT, ReturnT> callAdapter) {
    super(requestFactory, callFactory, responseConverter);
    this.callAdapter = callAdapter;
  }

  //adapt方法的实现,调用CallAdapter的adapt方法
  @Override protected ReturnT adapt(Call<ResponseT> call, Object[] args) {
    return callAdapter.adapt(call);
  }
}
  1. DefaultCallAdapterFactory
  • DefaultCallAdapterFactory实现了CallAdapted请添加图片描述
@Override public @Nullable CallAdapter<?, ?> get(
    Type returnType, Annotation[] annotations, Retrofit retrofit) {
  if (getRawType(returnType) != Call.class) {
    return null;
  }
  if (!(returnType instanceof ParameterizedType)) {
    throw new IllegalArgumentException(
        "Call return type must be parameterized as Call<Foo> or Call<? extends Foo>");
  }
  final Type responseType = Utils.getParameterUpperBound(0, (ParameterizedType) returnType);

  final Executor executor = Utils.isAnnotationPresent(annotations, SkipCallbackExecutor.class)
      ? null
      : callbackExecutor;

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

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

3. Call的enqueue方法

在这里插入图片描述

3.1 OkHttpCall的enqueue方法

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

  okhttp3.Call call;
  Throwable failure;

  synchronized (this) {
    if (executed) throw new IllegalStateException("Already executed.");
    executed = true;

    call = rawCall;
    failure = creationFailure;
    if (call == null && failure == null) {
      try {
        call = rawCall = createRawCall();
      } catch (Throwable t) {
        throwIfFatal(t);
        failure = creationFailure = t;
      }
    }
  }

  if (failure != null) {
    callback.onFailure(this, failure);
    return;
  }

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

  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
      }
    }
  1. 调用了parseResponse方法
  • 根据返回的不同状态码code来做不同的操作
Response<T> parseResponse(okhttp3.Response rawResponse) throws IOException {
  ResponseBody rawBody = rawResponse.body();

  // Remove the body's source (the only stateful object) so we can pass the response along.
  rawResponse = rawResponse.newBuilder()
      .body(new NoContentResponseBody(rawBody.contentType(), rawBody.contentLength()))
      .build();

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

  if (code == 204 || code == 205) {
    rawBody.close();
    return Response.success(null, rawResponse);
  }

  ExceptionCatchingResponseBody catchingBody = new ExceptionCatchingResponseBody(rawBody);
  try {
    T body = responseConverter.convert(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;
  }
}
  1. GsonConverterFactory
  • responseConverter就是我们在ServiceMethod的build方法里面调用createResponseConverter方法返回Converter。
  • 此前我们传入的是GsonConverterFactory
public final class GsonConverterFactory extends Converter.Factory {
  ...
  @Override
  public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations,
      Retrofit retrofit) {
    TypeAdapter<?> adapter = gson.getAdapter(TypeToken.get(type));
    return new GsonResponseBodyConverter<>(gson, adapter);
  }
   ....
}
  1. 有一个方法responseBodyConverter,他最终会创建GsonResponseBodyConverter
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 {
      T result = adapter.read(jsonReader);
      if (jsonReader.peek() != JsonToken.END_DOCUMENT) {
        throw new JsonIOException("JSON document was not fully consumed.");
      }
      return result;
    } finally {
      value.close();
    }
  }
}
  • 它的convert方法会将回调的数据转换为JSON格式的。
  • Call的enqueue方法主要做的就是用OkHttp来请求网络,将返回的Response进行数据转换并回调给UI线程。请添加图片描述
    请添加图片描述
    请添加图片描述
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值