Converter的作用是把http Request/Response相应的内容,序列化/反序列化。
常用的是json,但是xml, protocol buffers也是可以的。只要实现了Converter接口就可以。
而本文以Gson Converter为例。
public interface Converter<F, T>只有一个接口“T convert(F value)”,处理 http内容的序列化与反序列化。使用Gson的话,需要实现这个接口两次。一是Response Converter,从String到Object, 二是 Request Converter, 从Object到String。
public interface Converter<F, T> {
T convert(F value) throws IOException;
}
抽象类Converter.Factory定义了可以实现Converter的几种方式。responseBodyConverter()和requestBodyConverter()是一定要重写实现的。
public interface Converter<F, T> {
abstract class Factory {
public @Nullable Converter<ResponseBody, ?> responseBodyConverter(
Type type, Annotation[] annotations, Retrofit retrofit) {
return null;
}
public @Nullable Converter<?, RequestBody> requestBodyConverter(
Type type,
Annotation[] parameterAnnotations,
Annotation[] methodAnnotations,
Retrofit retrofit) {
return null;
}
public @Nullable Converter<?, String> stringConverter(
Type type, Annotation[] annotations, Retrofit retrofit) {
return null;
}
protected static Type getParameterUpperBound(int index, ParameterizedType type) {
return Utils.getParameterUpperBound(index, type);
}
protected static Class<?> getRawType(Type type) {
return Utils.getRawType(type);
}
}
}
GsonConverterFactory, 实现了两种生成Converter实现类的两种方式。也就是GsonResponseBodyConverter和GsonRequestBodyConverter。
GsonResponseBodyConverter,实现了 interface Converter, 把Response body的json String反序列化成对象。
GsonRequestBodyConverter,实现了 interface Converter, 把Request 的对象序列化成json String。返回给resquestBody。
Converter.Factory在Retrofit.java中出现的地方。所在的事情无非都是获取GsonConverterFactory中定义的Converter. 至于nextRequestBodyConverter和nextResponseBodyConverter。
如果有多个Converter.Factory的实现类。比如除了添加了GsonConverterFactory,还有添加了FastJsonConverterFactory,或者其他XML,二进制的解析方式。
类似于这样:
mRetrofit = new Retrofit.Builder()
.baseUrl(host)
.addConverterFactory(GsonConverterFactory.create())
.addConverterFactory(FastJsonConverterFactory.create())
public final class Retrofit {
final List<Converter.Factory> converterFactories;
Retrofit(...
List<Converter.Factory> converterFactories,) {
...
this.converterFactories = converterFactories; // Copy+unmodifiable at call site.
}
public List<Converter.Factory> converterFactories() {
return converterFactories;
}
public <T> Converter<T, RequestBody> requestBodyConverter(
Type type, Annotation[] parameterAnnotations, Annotation[] methodAnnotations) {
return nextRequestBodyConverter(null, type, parameterAnnotations, methodAnnotations);
}
public <T> Converter<T, RequestBody> nextRequestBodyConverter(
@Nullable Converter.Factory skipPast,
Type type,
Annotation[] parameterAnnotations,
Annotation[] methodAnnotations) {
}
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) {
}
public <T> Converter<T, String> stringConverter(Type type, Annotation[] annotations) {
}
}
使用的地方:
1. 在RequestFactory,用到了GsonRequestBodyConverter。
比如在Part中,这里的converter就是通过Retrofit传过来的。
static final class Part<T> extends ParameterHandler<T> {
private final Method method;
private final int p;
private final okhttp3.Headers headers;
private final Converter<T, RequestBody> converter;
Part(Method method, int p, okhttp3.Headers headers, Converter<T, RequestBody> converter) {
this.method = method;
this.p = p;
this.headers = headers;
this.converter = converter;
}
@Override
void apply(RequestBuilder builder, @Nullable T value) {
if (value == null) return; // Skip null values.
RequestBody body;
try {
body = converter.convert(value);
} catch (IOException e) {
throw Utils.parameterError(method, p, "Unable to convert " + value + " to RequestBody", e);
}
builder.addPart(headers, body);
}
}
2. 在OkHttpCall.java, 使用了GsonResponseBodyConverter。
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;
}
}