写点什么

Android 框架解析:深入理解 Retrofit 实现

作者:拭心
  • 2021 年 12 月 05 日
  • 本文字数:11584 字

    阅读完需:约 38 分钟

Android 框架解析:深入理解 Retrofit 实现

OkHttp3 由于其易于拓展、灵活配置同时缓存策略的通用性、连接复用的高性能,已经基本成为目前安卓开发者使用率最高的“基础网络框架”。


之所以强调“基础网络框架”,是因为现在市面上有许多基于 OkHttp3 再次封装的网络请求库,其中比较著名的是 Retrofit


Retrofit 独特的设计使得使用它发起网络请求就像服务端写接口一样,先定义一个 Service 然后直接调用方法即可,不用自己创建实现。


另外 Retrofit 可以和 Gson RxJava 无缝结合,这让它的使用更加方便。


接下来我们将从 Retrofit 的使用例子出发,逐步深入地了解它方便使用的背后原理。


文章主要内容:


  • Retrofit 请求实现流程基本认识

  • Retrofit 如何拿到请求信息

  • Retrofit 如何转换请求、响应信息

Retrofit 请求实现流程基本认识

Retrofit 的使用非常简单,基本分四步:


  1. 定义接口、方法、参数、返回值

  2. 构造 Retrofit

  3. 调用 retrofit.create() 获取实例

  4. 调用方法获取返回值,执行接下来的异步或者同步请求


1.首先定义接口、方法、参数、返回值


public interface IApiService {    @GET("users/{user}/repos")    Call<List<String>> listRepos(@Path("user") String user);
@GET("users/{user}/repos") Observable<List<String>> listReposObservable(@Path("user") String user);}
复制代码


一般来说方法的返回值是 retrofit2.Call,如果使用 RxJava 的话也可以是 Observable


在 OkHttp 中,Call 的唯一实现就是 RealCall,它表示一个准备好被执行的请求;在 Retrofit 中也定义了一个 Call 接口,不过它俩的级别不一样,相较于 OkHttp.CallRetrofit.Call 增加了更多信息,这个我们后面介绍。


2.构造 Retrofit


Retrofit retrofit = new Retrofit.Builder()        .baseUrl("https://api.github.com")        .addCallAdapterFactory(RxJavaCallAdapterFactory.create())        .addConverterFactory(GsonConverterFactory.create())        .build();
复制代码


构造 Retrofit 的参数不多,就这么几个:


public static final class Builder {  private final Platform platform;  private @Nullable okhttp3.Call.Factory callFactory;    //默认是 OkHttpClient  private HttpUrl baseUrl;  private final List<Converter.Factory> converterFactories = new ArrayList<>();    //转换器  private final List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>();    //适配器,将 Call 转换成指定的类型  private @Nullable Executor callbackExecutor;  private boolean validateEagerly;  //...}
复制代码


其中 ConverterCallAdapter 是我们后面要关注的重点, ``Retrofit` 之所以灵活好用,离不开这两位大将。


3.调用 retrofit.create() 获取实例


retrofit.create(IApiService.class)
复制代码


这里用到了动态代理 Proxy.newProxyInstance() ,生成实例并且代理所有方法,当我们调用某个方法时,会调用这个代理的invoke() 方法,这也是 Retrofit 的重点,后面详细分析。


//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 { //... } });}
复制代码


4.调用方法获取返回值,执行异步或者同步请求


retrofit.create(IApiService.class)        .listRepos("shixinzhang")    //这里返回了 retrofit2.Call        .enqueue(new Callback<List<String>>() {            @Override            public void onResponse(Call<List<String>> call, Response<List<String>> response) {                List<String> body = response.body();

}
@Override public void onFailure(Call<List<String>> call, Throwable t) {
} });
复制代码


调用方法后之所以可以调用 enqueue() 方法,是因为我们在定义方法时返回值是 retrofit2.Call


retrofit2.Call 的实现类是 OkHttpCall,它的成员属性有一个 okhttp3.Call,发起请求就是通过 okhttp3.Call 来的:


final class OkHttpCall<T> implements Call<T> {  private final ServiceMethod<T, ?> serviceMethod;  private final @Nullable Object[] args;
private volatile boolean canceled; private @Nullable okhttp3.Call rawCall; private @Nullable Throwable creationFailure; private boolean executed; //...}
复制代码


Retrofit 发起异步请求的实现:


//OkHttpCall.enqueue()@Override public void enqueue(final Callback<T> callback) {  checkNotNull(callback, "callback == null");
okhttp3.Call call; //... 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) { callFailure(e); return; }
try { callback.onResponse(OkHttpCall.this, response); } catch (Throwable t) { t.printStackTrace(); } }
@Override public void onFailure(okhttp3.Call call, IOException e) { callFailure(e); } //... });}
复制代码


拿到响应后调用了 parseResponse() 方法,这个方法把 okhttp3.Response 转成了 Retrofit.Response


Response<T> parseResponse(okhttp3.Response rawResponse) throws IOException {  ResponseBody rawBody = rawResponse.body();  //...  int code = rawResponse.code();  if (code < 200 || code >= 300) {    try {      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); }
ExceptionCatchingRequestBody catchingBody = new ExceptionCatchingRequestBody(rawBody); try { T body = serviceMethod.toResponse(catchingBody); //从响应里解析、转成指定的类型 return Response.success(body, rawResponse); } catch (RuntimeException e) { throw e; }}
复制代码


可以看到,这个 parseResponse() 方法就是做了我们经常做的根据响应码判断,回调 success 或者 error 回调。


在方法的最后调用了 serviceMethod.toResponse()okhttp3.Response 转换成指定的类型,具体的细节我们后面介绍。


OK,至此我们对 Retrofit 的发起请求到拿到响应有了基本的认识,用一张图概括一下:



接下来对一些核心细节进行深入学习。


上篇文章的的流程图中,我们有这些疑问:


  1. 接口的实现代理做了哪些额外操作?

  2. 接口中的信息是如何转换成请求信息?

  3. 拿到响应后是如何转换成指定的类型?


接下来我们一起来解决这些问题。


Retrofit 核心机制实现分析

接口的代理做了哪些操作

我们知道接口的动态代理实现是在 Retrofit.create() 方法中:


public <T> T create(final Class<T> service) {  Utils.validateServiceInterface(service);    //验证是不是接口,有没有继承别的接口  if (validateEagerly) {    eagerlyValidateMethods(service); //预加载,默认 validateEagerly 是 false
} 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 { //如果是 Object 的方法就直接调用 if (method.getDeclaringClass() == Object.class) { return method.invoke(this, args); } //... ServiceMethod<Object, Object> serviceMethod = (ServiceMethod<Object, Object>) loadServiceMethod(method); OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args); return serviceMethod.adapt(okHttpCall); } });}
复制代码


可以看到,这个 create() 方法首先验证了传入的 Class 是不是接口,然后为接口创建了代理实例。


以后调用这个实例的方法,都将经过这个匿名内部类 InvocationHandlerinvoke() 方法。


我们知道任何类都会默认继承 Object 类,因此在 invoke() 方法中,遇到 Object 类的方法直接进行调用,不做任何处理。


然后就到了关键部分了:


                //InvocationHandler.invoke()        @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.adapt(okHttpCall);        }
复制代码


在这部分做了三件事:



  1. 调用 loadServiceMethod() ,参数是当前调用的方法,返回一个 ServiceMethod 实例

  2. 创建了一个 OkHttpCall 实例,参数是 serviceMethod 和当前调用方法传递的参数

  3. 调用了 serviceMethod.adapt(okHttpCall) 返回被代理方法的返回值


先来看看这个 ServiceMethod 是干什么的。


正如其名,一个 ServiceMethod 对象对应于一个接口的方法,它的职责是:把对接口方法的调用转为一次 HTTP 调用(敲黑板,这是重点)。


它的成员属性有很多:


private final okhttp3.Call.Factory callFactory;private 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;
复制代码


除了关于请求信息的,其中最重要的就是两个: CallAdapterConverter<F, T>


  • CallAdapter 的作用是将我们在接口的方法中声明的返回值类型转成 retrofit2.Call,如果我们直接声明方法的返回值就是 retrofit2.CallCallAdapter 就不需要做什么转换了,后面再详细介绍

  • Converter<F, T> 的作用是将用户的请求/响应类型 和 HTTP 的请求/响应类型进行转换,一般有两个,作用其实类似 OkHttpBridgeInterceptor


回到 Retrofit.create() 中创建的代理的 invoke() 方法,先是调用了 loadServiceMethod() 方法返回一个 ServiceMethod,我们看看这个方法做了什么:



private final Map<Method, ServiceMethod<?, ?>> serviceMethodCache = new ConcurrentHashMap<>();
ServiceMethod<?, ?> loadServiceMethod(Method method) { ServiceMethod<?, ?> result = serviceMethodCache.get(method); if (result != null) return result;
synchronized (serviceMethodCache) { result = serviceMethodCache.get(method); if (result == null) { //缓存里没有就新建一个 result = new ServiceMethod.Builder<>(this, method).build(); serviceMethodCache.put(method, result); } } return result;}
复制代码


可以看到,这个方法先去一个 Map 里根据 Method 方法对象去查询有没有之前保存的 ServiceMethod,有就直接返回,没有就调用 ServiceMethod.Builder<>(this, method).build(); 新建一个然后保存。


去瞅瞅这个 Builder:


//ServiceMethod.Builderstatic final class Builder<T, R> {  final Retrofit retrofit;  //...  Converter<ResponseBody, T> responseConverter;  CallAdapter<T, R> callAdapter;
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(); //拿到可以处理当前接口方法的 ``CallAdapter`` responseType = callAdapter.responseType(); //... responseConverter = createResponseConverter(); //拿到可以处理当前接口方法的 ``responseConverter`` for (Annotation annotation : methodAnnotations) { parseMethodAnnotation(annotation); } //... return new ServiceMethod<>(this); } //...}
复制代码


ServiceMethod.Builderbuild() 方法中主要做了 3 件事:



  1. 实例化用于处理当前接口方法的 callAdapterresponseConverter

  2. 解析方法上的注解信息


来分别看看如何实现的。


前面提到:


  • CallAdapter 的作用是将我们在接口的方法中声明的返回值类型转成 retrofit2.Call

  • 一个 ServiceMethod 对象对应于一个接口的方法


因此不同的方法如果返回值不同, ServiceMethod 中的CallAdapter 是不同的。


我们来看看 ServiceMethod 是怎么找到能处理当前方法的 CallAdapter


private CallAdapter<T, R> createCallAdapter() {  Type returnType = method.getGenericReturnType();  if (Utils.hasUnresolvableType(returnType)) {    //首先判断返回值类型    throw methodError(//...);  }  if (returnType == void.class) {    throw methodError("//...");  }  Annotation[] annotations = method.getAnnotations();  try {    //调用 retrofit 的方法    return (CallAdapter<T, R>) retrofit.callAdapter(returnType, annotations);  } catch (RuntimeException e) {     //...  }}
复制代码


如果你记不住 CallAdapter 是干嘛的,看到上面这个方法的前两个判断或许就能记住了,它是要处理返回值的,所以在创建前需要检查方法的返回值是否合理。


最后调用了 retrofit.callAdapter(returnType, annotations);:


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 = callAdapterFactories.indexOf(skipPast) + 1; //遍历 Retrofit 创建时添加的 callAdapterFactory for (int i = start, count = callAdapterFactories.size(); i < count; i++) { CallAdapter<?, ?> adapter = callAdapterFactories.get(i).get(returnType, annotations, this); if (adapter != null) { return adapter; } }
//... throw new IllegalArgumentException(builder.toString());}
复制代码


可以看到,最后找适用于当前方法的 CallAdapter 是通过遍历 Retrofit 创建时添加的 CallAdapter.Factory,然后调用每一个 factory 的 get() 方法,如果不为空表示能处理,就返回这个 CallAdapter


Retrofit 中我们主要用到两个 CallAdapterFactory:


  1. DefaultCallAdapterFactory 处理 Retrofit 默认返回值 Call<T>

  2. RxJavaCallAdapterFactory 处理返回值为 Observable<T>


我们来简单看看 DefaultCallAdapterFactory.get() 方法:


final class DefaultCallAdapterFactory extends CallAdapter.Factory {  //...  @Override  public CallAdapter<?, ?> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {    if (getRawType(returnType) != Call.class) {   //用于处理返回值是 Call       return null;    }
final Type responseType = Utils.getCallResponseType(returnType); return new CallAdapter<Object, Call<?>>() { //创建一个 CallAdapter,直接返回 Call @Override public Type responseType() { return responseType; }
@Override public Call<Object> adapt(Call<Object> call) { return call; } }; }}
复制代码


可以看到,默认的这个 DefaultCallAdapterFactory只能处理返回值是 Call,它返回的 CallAdapter 没有做额外工作,直接返回了这个返回值。


** ServiceMethod 寻找能处理当前方法的 Converter 的逻辑也是类似,去 Retrofit 的 converterFactory 列表里遍历寻找: **


public <T> Converter<ResponseBody, T> responseBodyConverter(Type type, Annotation[] annotations) {  return nextResponseBodyConverter(null, type, annotations);}public <T> Converter<ResponseBody, T> nextResponseBodyConverter(    @Nullable Converter.Factory skipPast, Type type, Annotation[] annotations) {  //...  int start = converterFactories.indexOf(skipPast) + 1;  for (int i = start, count = converterFactories.size(); i < count; i++) {    Converter<ResponseBody, ?> converter =        converterFactories.get(i).responseBodyConverter(type, annotations, this);    if (converter != null) {      return (Converter<ResponseBody, T>) converter;    }  }  //...  throw new IllegalArgumentException(builder.toString());}
复制代码


小结一下:创建一个 ServiceMethod 是要给它找能处理当前返回值的 CallAdapter,它是通过去 RetrofitCallAdapter.Factory 列表(final List<CallAdapter.Factory> callAdapterFactories; )里挨个调用 get() 方法来寻找的,找 responseConverter 响应转换器也是一样的。



OK,ServiceMethod 的前两步我们都了解了,最后看一下如何解析方法上的注解信息


//ServiceMethod.Builder.build()public ServiceMethod build() {  //...  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]; //... Annotation[] parameterAnnotations = parameterAnnotationsArray[p]; parameterHandlers[p] = parseParameter(p, parameterType, parameterAnnotations); }
复制代码


可以看到解析方法上的注解信息主要分两步:


  1. 遍历方法上的所有注解 methodAnnotations 解析请求方法和地址

  2. 遍历参数中的所有注解 parameterAnnotationsArray 解析参数,比如相对路径、查询值,解析结果保存到 ParameterHandler


具体代码比较简单,这里就不再赘述了。



了解了 ServiceMethod 的创建后,代理方法的第二步是创建了一个 OkHttpCall,前面介绍请求流程时已经介绍过, OkHttpCall 就是对 okhttp3.Call 的封装,它的同步异步请求都是通过调用 okhttp3.Call 的方法实现的。


调用 okhttp3.Call 需要传递 okhttp.Request 请求信息,这里的请求信息就是通过持有前面创建的 ServiceMethod 来实现的。


在调用 OkHttpCall 的同步、异步请求时,会先调用 OkHttpCall.createRawCall() 方法创建一个 okhttp3.Call


private okhttp3.Call createRawCall() throws IOException {  okhttp3.Call call = serviceMethod.toCall(args);  if (call == null) {    throw new NullPointerException("Call.Factory returned null.");  }  return call;}
复制代码


可以看到是调用的 ServiceMethodtoCall() 方法创建的,这个 ServiceMethod 太关键了,一定要记住它。


//ServiceMethod.toCall()okhttp3.Call toCall(@Nullable Object... args) throws IOException {  RequestBuilder requestBuilder = new RequestBuilder(httpMethod, baseUrl, relativeUrl, headers,      contentType, hasBody, isFormEncoded, isMultipart);  ParameterHandler<Object>[] handlers = (ParameterHandler<Object>[]) parameterHandlers;  int argumentCount = args != null ? args.length : 0;  //...  for (int p = 0; p < argumentCount; p++) {    handlers[p].apply(requestBuilder, args[p]);  }
return callFactory.newCall(requestBuilder.build());}
复制代码


可以看到,这个方法就是把前面解析注解拿到的数据都组装起来,创建一个 Request 传递给 OkHttpClient



前两步清楚了,最后看第三步 serviceMethod.adapt(okHttpCall):


//ServiceMethod.adapt()T adapt(Call<R> call) {  return callAdapter.adapt(call);}
复制代码


我们知道当返回值类型是 CallCallAdapter 的不做任何操作,也就是做,调用这个 ServiceMethod.adapt() 方法的作用就是返回上一步创建的 OkHttpCall


当我们使用 RxJava 时返回值是 Observable,这时的 CallAdapter 的作用就是将 Observable 转换成 OkHttpCall


OK,至此我们对代理做了什么算是彻底了解了,总结一下:


  1. 解析注解,创建能处理当前方法的 CallAdapterConverter

  2. 创建封装底层 okhttp3.CallOkHttpCall,这个类在执行网络请求时,会根据之前创建的 ServiceMethod 来组装请求信息

  3. 将方法的返回值转换成要做请求的 OkHttpCall,当返回值是 Call 时就不做任何处理


如果有使用 retrofit2.http.Body 修饰的参数,这个对象会被某一个 Converter.Factory 实例转换成 OkHttp 请求体(okhttp3.RequestBody


Converter<F, T>的作用是将用户的请求/响应类型 和 HTTP 的请求/响应类型进行转换,一般有两个,作用其实类似OkHttpBridgeInterceptor``

Retrofit 如何拿到请求信息

我们使用 Retrofit 时只要定义接口和方法,然后使用注解表示请求方法、请求参数以及输入返回值即可。



那它进行网络请求时是如何拿到请求信息的呢?


上一节中介绍代理拦截方法时做的工作时,我们已经得到了答案:


  1. Retrofit.create() 方法为接口创建动态代理

  2. 当调用接口的方法时,会调用拦截的 invoke() 方法

  3. 在这个方法里先是创建了 ServiceMethod(它可以解析方法上的注解和参数的注解,同时寻找能处理当前方法的 CallAdapterConverter

  4. 然后创建了封装底层请求的 OkHttpCall,这个类会在做请求时,根据 ServiceMethod 的信息创建一个 okhttp3.Request,从而创建一个 okhttp3.Call 做网络请求

Retrofit 如何转换请求、响应信息

经过前面的学习我们知道,RetrofitConverter 就是负责转换 请求、响应信息 的。它一般有两种:


  1. 将使用 @Body 修饰的参数转换成请求体

  2. 将网络响应的响应体 ResponseBody 转换成用户指定的类型


先看如何实现将使用 @Body 修饰的参数转换成请求体。


我们使用 RetrofitPOST 请求时,可以使用 @Body 注解修饰一个实体,它表示要提交的请求体:


public interface IApiService {
@POST("users//repos/update") Call<List<Result>> updateRepos(@Body RepoInfo repoInfo);}
复制代码


我们知道 ServiceMethod 负责解析方法参数的注解,我们来看看它遇到 @Body 是如何解析的吧:


private ParameterHandler<?> parseParameterAnnotation(  //...  } else if (annotation instanceof Body) {    //...    Converter<?, RequestBody> converter;    try {      converter = retrofit.requestBodyConverter(type, annotations, methodAnnotations);    } catch (RuntimeException e) {      //...    }    gotBody = true;    return new ParameterHandler.Body<>(converter);  }  //...}
复制代码


可以看到,在解析参数注解时,遇到注解是 Body 时,会调用 retrofit.requestBodyConverter() ,这个方法和前面寻找转换响应数据的 responseConverter 一样,都是遍历 Retrofit 中的转换器工厂列表。


最常使用的转换器工厂是 GsonConverterFactory,我们来看看它定义的请求体解析器是什么样的:


//GsonConverterFactory.requestBodyConverter()@Overridepublic Converter<?, RequestBody> requestBodyConverter(Type type,    Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) {  TypeAdapter<?> adapter = gson.getAdapter(TypeToken.get(type));  return new GsonRequestBodyConverter<>(gson, adapter);}//GsonRequestBodyConverter.convert()@Override public RequestBody convert(T value) throws IOException {  Buffer buffer = new Buffer();  Writer writer = new OutputStreamWriter(buffer.outputStream(), UTF_8);  JsonWriter jsonWriter = gson.newJsonWriter(writer);  adapter.write(jsonWriter, value);  jsonWriter.close();  return RequestBody.create(MEDIA_TYPE, buffer.readByteString());}
复制代码


可以看到,使用 Gson 实现的请求体转换器比较简单,就是拿到 Type 后创建一个 TypeAdapter ,然后读取数据,将它转成 RequestBody


接着看看拿到网络响应响应体 ResponseBody 后,如何转换成用户指定的类型。


OkHttpCall 的同步或者异步请求最后,都调用了 parseResponse() 方法,这个方法除了根据响应码做回调,最后还做了转换工作:


//OkHttpCall.parseResponseResponse<T> parseResponse(okhttp3.Response rawResponse) throws IOException {  //...  int code = rawResponse.code();  if (code < 200 || code >= 300) {    try {      ResponseBody bufferedBody = Utils.buffer(rawBody);      return Response.error(bufferedBody, rawResponse);    } finally {      rawBody.close();    }  }  //...  ExceptionCatchingRequestBody catchingBody = new ExceptionCatchingRequestBody(rawBody);  try {    T body = serviceMethod.toResponse(catchingBody);    return Response.success(body, rawResponse);  } catch (RuntimeException e) {    //...    throw e;  }}
复制代码


又见 ServiceMethod,这哥们从请求开始到请求结束,一直负责重要的功能,大家一定要记住它!!!


ServiceMethod.toResponse() 方法也很简单,就是调用转换器:


//ServiceMethod.toResponseR toResponse(ResponseBody body) throws IOException {  return responseConverter.convert(body);}
复制代码


还是看看常用的 Gson 响应转换器:


//GsonConverterFactory.responseBodyConverter()public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations,    Retrofit retrofit) {  TypeAdapter<?> adapter = gson.getAdapter(TypeToken.get(type));  return new GsonResponseBodyConverter<>(gson, adapter);}//GsonResponseBodyConverter.convert()@Override public T convert(ResponseBody value) throws IOException {  JsonReader jsonReader = gson.newJsonReader(value.charStream());  try {    return adapter.read(jsonReader);  } finally {    value.close();  }}
复制代码


很简单就两步:


  1. 根据方法中的返回值数据类型 Type 创建 TypeAdapter

  2. 调用 JsonReader 进行读取,将 ResponseBody 转换成指定的类型


具体 Gson 原理这里就暂不赘述了。


OK 小结一下 Retrofit 如何转换请求、响应信息: 两个转换器搞定!

Retrofit 请求实现流程总结

一张图总结 Retrofit 网络请求实现原理:



Retrofit 中最核心的就这几点:


  1. 动态代理,代理类做了什么工作要清楚

  2. 老熟人 ServiceMethod 都做了什么重要的工作

  3. CallAdapter 负责将方法里的返回值转换成上层的 OkHttpCall

  4. 两个 Converter 分别实现自己传的对象到请求体、响应体到自己定义的对象的转换


看着流程图能把这四点说明白,你就掌握了!

发布于: 1 小时前阅读数: 13
用户头像

拭心

关注

Never Settle! 2017.11.30 加入

字节跳动高级 Android 工程师,主要从事性能优化相关工作

评论

发布
暂无评论
Android 框架解析:深入理解 Retrofit 实现