retrofit中关于Gson解析的源码分析

444 阅读3分钟

这篇文章的主旨是在于分析retrofit如何和Gson合作解析返回的json数据

1.首先需要知道如何在retrofit中使用Gson解析,最常见的用法如下

  retrofit = Retrofit.Builder()
                            .baseUrl(url)  
                            .client(client!!)
                            .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                            .addConverterFactory(GsonConverterFactory.create())  //这个地方就是设置Gson的地方
                            .build()

2.接着查看 addConverterFactory(Converter.Factory factory)这个方法

   /** Add converter factory for serialization and deserialization of objects. */
    public Builder addConverterFactory(Converter.Factory factory) {
      converterFactories.add(checkNotNull(factory, "factory == null"));//这个比较简单就是判空然后在converterFactories这个list添加
      return this;
    }

converterFactories是一个泛型为Converter.Factory的arraylist,从字面理解为一个转换器的工厂,这里是一个工程模式,稍后会有详解,接着就要看这个list被使用的地方,这个list一共有4个方法在用,但是其中三个都是在添加新的工厂,只有一个真正有用,这个方法就是Retrofit build()

  // Make a defensive copy of the converters.   制作一份转换器的防御性副本(有点怪怪的,翻译不好)
      List<Converter.Factory> converterFactories = new ArrayList<>(this.converterFactories);

      return new Retrofit(callFactory, baseUrl, converterFactories, adapterFactories,
          callbackExecutor, validateEagerly);//这里便是最终使用的地方

new Retrofit的这个方法也只是做了个赋值

this.converterFactories = unmodifiableList(converterFactories); // Defensive copy at call site.
//转换成不可修改的列表并赋值

这个converterFactories在4个方法中被使用,这四个方法是

  • List<Converter.Factory> converterFactories()
  • Converter<T, RequestBody> nextRequestBodyConverter( @Nullable Converter.Factory skipPast, Type type, Annotation[] parameterAnnotations, Annotation[] methodAnnotations)
  • Converter<ResponseBody, T> nextResponseBodyConverter( @Nullable Converter.Factory skipPast, Type type, Annotation[] annotations)
  • Converter<T, String> stringConverter(Type type, Annotation[] annotations)
    这边主要分析nextResponseBodyConverter这个方法这个方法主要被调用的方法是
  • responseBodyConverter(Type type, Annotation[] annotations)
    这个方法只被ServiceMethod类的createResponseConverter方法->build然后被retrofit类的loadServiceMethod(Method method)最终的方法是public T create(final Class service)也就是我们retrofit常用的create方法
var serviceHome: ApiService = getRetrofit(UriConstant.BASE_URL_TEST)!!.create(ApiService::class.java)

这里需要讲一下GsonConverterFactory.create()这个方法

// Converter.Factory这是一个抽象类
public final class GsonConverterFactory extends Converter.Factory {
  /**
   * Create an instance using a default {@link Gson} instance for conversion. Encoding to JSON and
   * decoding from JSON (when no charset is specified by a header) will use UTF-8.
   */
  public static GsonConverterFactory create() {
    return create(new Gson());
  }

  /**
   * Create an instance using {@code gson} for conversion. Encoding to JSON and
   * decoding from JSON (when no charset is specified by a header) will use UTF-8.
   */
  @SuppressWarnings("ConstantConditions") // Guarding public API nullability.
  public static GsonConverterFactory create(Gson gson) {
    if (gson == null) throw new NullPointerException("gson == null");
    return new GsonConverterFactory(gson);
  }

  private final Gson gson;

  private GsonConverterFactory(Gson gson) {
    this.gson = gson;
  }
  //nextResponseBodyConvertery()也就是调用这个方法
  @Override
  public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations,
      Retrofit retrofit) {
    TypeAdapter<?> adapter = gson.getAdapter(TypeToken.get(type));
    return new GsonResponseBodyConverter<>(gson, adapter); //这个方法就是生成一个转化器将responBaody进行转化
  }

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

看一下这个转化器

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;
  }
  //这个是一个实现Converter接口的一个方法
  @Override public T convert(ResponseBody value) throws IOException {
    JsonReader jsonReader = gson.newJsonReader(value.charStream());
    try {
      return adapter.read(jsonReader);
    } finally {
      value.close();
    }
  }
}

Converter这个接口convert方法被用在许多地方,主要看一下ServiceMethod这个类的调用,

R toResponse(ResponseBody body) throws IOException {
    return responseConverter.convert(body);
  }
 //okhttpcall类,这个方法会在enqueue这个方法调用
Response<T> parseResponse(okhttp3.Response rawResponse) throws IOException {
    ResponseBody rawBody = rawResponse.body();

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

    ExceptionCatchingRequestBody catchingBody = new ExceptionCatchingRequestBody(rawBody);
    try {
    //这里进行调用
      T body = serviceMethod.toResponse(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;
    }
  }