这篇文章的主旨是在于分析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;
}
}