如果http方法接口的返回值,不需要转换,甚至不需要返回值, 就像下面的代码一样。那么Retrofit是怎么做的呢?
public interface IDeviceService {
@POST("v1/info/pair")
Call<Void> pairDevice1(@HeaderMap Map<String, String> heads, @Body Device device);
@POST("v1/info/pair")
Call<ResponseBody> pairDevice2(@HeaderMap Map<String, String> heads, @Body Device device);
@POST("v1/info/pair")
@Streaming
Call<ResponseBody> pairDevice3(@HeaderMap Map<String, String> heads, @Body Device device);
}
答案在BuiltInConverters类里面, 作者已经帮我们写好了这些默认的Converter。并且在初始化Retrofit对象的时候,已经添加到converterFactories数组里面去了。
final class BuiltInConverters extends Converter.Factory {
/** Not volatile because we don't mind multiple threads discovering this. */
private boolean checkForKotlinUnit = true;
@Override
public @Nullable Converter<ResponseBody, ?> responseBodyConverter(
Type type, Annotation[] annotations, Retrofit retrofit) {
if (type == ResponseBody.class) {
return Utils.isAnnotationPresent(annotations, Streaming.class)
? StreamingResponseBodyConverter.INSTANCE
: BufferingResponseBodyConverter.INSTANCE;
}
if (type == Void.class) {
return VoidResponseBodyConverter.INSTANCE;
}
if (checkForKotlinUnit) {
try {
if (type == Unit.class) {
return UnitResponseBodyConverter.INSTANCE;
}
} catch (NoClassDefFoundError ignored) {
checkForKotlinUnit = false;
}
}
return null;
}
@Override
public @Nullable Converter<?, RequestBody> requestBodyConverter(
Type type,
Annotation[] parameterAnnotations,
Annotation[] methodAnnotations,
Retrofit retrofit) {
if (RequestBody.class.isAssignableFrom(Utils.getRawType(type))) {
return RequestBodyConverter.INSTANCE;
}
return null;
}
static final class VoidResponseBodyConverter implements Converter<ResponseBody, Void> {
static final VoidResponseBodyConverter INSTANCE = new VoidResponseBodyConverter();
@Override
public Void convert(ResponseBody value) {
value.close();
return null;
}
}
static final class UnitResponseBodyConverter implements Converter<ResponseBody, Unit> {
static final UnitResponseBodyConverter INSTANCE = new UnitResponseBodyConverter();
@Override
public Unit convert(ResponseBody value) {
value.close();
return Unit.INSTANCE;
}
}
static final class RequestBodyConverter implements Converter<RequestBody, RequestBody> {
static final RequestBodyConverter INSTANCE = new RequestBodyConverter();
@Override
public RequestBody convert(RequestBody value) {
return value;
}
}
static final class StreamingResponseBodyConverter
implements Converter<ResponseBody, ResponseBody> {
static final StreamingResponseBodyConverter INSTANCE = new StreamingResponseBodyConverter();
@Override
public ResponseBody convert(ResponseBody value) {
return value;
}
}
static final class BufferingResponseBodyConverter
implements Converter<ResponseBody, ResponseBody> {
static final BufferingResponseBodyConverter INSTANCE = new BufferingResponseBodyConverter();
@Override
public ResponseBody convert(ResponseBody value) throws IOException {
try {
// Buffer the entire body to avoid future I/O.
return Utils.buffer(value);
} finally {
value.close();
}
}
}
static final class ToStringConverter implements Converter<Object, String> {
static final ToStringConverter INSTANCE = new ToStringConverter();
@Override
public String convert(Object value) {
return value.toString();
}
}
}
不返回很简单,
if (type == Void.class) {
return VoidResponseBodyConverter.INSTANCE;
}
在VoidResponseBodyConverter中直接返回了null.
在接口定义成Call<Void>就好了。
重点说一下,直接返回ResponseBody。
但是返回ResponseBody又有两种, 一种是已经在inputstream流里面,帮你读出内容了,是BufferingResponseBodyConverter。还有一种是没读出来,需要你自己去读StreamingResponseBodyConverter。
那这两者是如何区分的呢?是看接口上是否添加了@Streaming
下面这段代码就是判断,接口方法上有没有添加@Streaming, 决定相应的Converter。
if (type == ResponseBody.class) {
return Utils.isAnnotationPresent(annotations, Streaming.class)
? StreamingResponseBodyConverter.INSTANCE
: BufferingResponseBodyConverter.INSTANCE;
}
Retrofit的作者们想的很周到。