前言
Retrofit是Square公司开源的一个针对OkHttp网络请求接口进行二次封装的框架,其网络请求的实质工作仍是由OkHttp来完成,主要工作是将网络请求通过一系列注解的形式进行拆解,并在最终执行网络请求前,将注解解析生成OkHttp请求所需的Okhttp3.Call。通过分析Retrofit源码,来达到深入理解Retrofit的工作流程与原理,以及学习一些值得借鉴的设计模式和启发一些解决问题的思路。
对于源码中各种参数类型的相关知识,如有不理解的地方,可以参考贾博岩的两篇文章:我眼中的Java-Type体系。
https://www.jianshu.com/p/7649f86614d3
https://www.jianshu.com/p/e8eeff12c306
基本使用
第一步:集成
implementation 'com.squareup.retrofit2:retrofit:2.4.0'
implementation 'com.squareup.retrofit2:converter-gson:2.4.0'
implementation 'com.squareup.retrofit2:adapter-rxjava2:2.4.0'
第二步:创建接口
public interface JianShuApi {
@GET("user/{userName}/info")
Observable<ResponseBody> getPersonalInfo(@Path("userName") String userName);
}
第三步:配置Retrofit并实例化
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://www.jianshu.com")
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.addConverterFactory(GsonConverterFactory.create())
.build();
第四步:获取接口对象
JianShuApi api = retrofit.create(JianShuApi.class);
第五步:执行请求
Call<ResponseBody> call = api.getPersonalInfo("zhangSanLisi");
//异步请求
call.enqueue(new Callback<ResponseBody>() {
@Override
public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
//成功回调
}
@Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
//失败回调
}
});
//同步请求
try {
Response<ResponseBody> response = call.execute();
} catch (IOException e) {
e.printStackTrace();
}
源码分析
下面我们按照使用流程来分析:
1、自定义接口类
里面的请求方法,主要通过注解的方式来实现各种参数的灵活配置。如常用的请求方式@POST @GET,添加请求参数的@Query @QueryMap,大文件下载@Streaming,多文件提交@Multipart,请求头内容@Header @Headers...,具体注解使用请参考retrofit2.http里面的内容,每个注解都有相关的注释。
2、Retrofit.Builder
通过Retrofit.Builder构造者模式来实例化Retrofit对象,主要可配置的内容如下:
public static final class Builder {
// 具体使用平台,Platform.get()方法来获取,这里只分析Android
private final Platform platform;
// 指定用来构建Call实例的Call.Factory类
private @Nullable okhttp3.Call.Factory callFactory;
// 请求的baseUrl,注释建议我们使用相对路径的方式来配置
// Base URL: http://example.com/api/
// Endpoint: foo/bar/
// Result: http://example.com/api/foo/bar/
private HttpUrl baseUrl;
// 用于对象序列化(serialization)和反序列化(deserialization),常用GsonConverterFactory
private final List<Converter.Factory> converterFactories = new ArrayList<>();
// 请求返回类型(除了Call之外),若Retrofit结合RxJava一起使用,那么就可以添加RxJava2CallAdapterFactory
// 来返回Observable类型,无缝对接RxJava
private final List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>();
// 异步回调执行者
private @Nullable Executor callbackExecutor;
// 是否提前校验注解方法
private boolean validateEagerly;
......
public Retrofit build() {
// 必须指定baseUrl,否则异常
if (baseUrl == null) {
throw new IllegalStateException("Base URL required.");
}
//默认OkHttpClient来创建请求Call
okhttp3.Call.Factory callFactory = this.callFactory;
if (callFactory == null) {
callFactory = new OkHttpClient();
}
// Android平台默认回调在主线程
Executor callbackExecutor = this.callbackExecutor;
if (callbackExecutor == null) {
callbackExecutor = platform.defaultCallbackExecutor();
}
// 默认添加一个CallAdapter和Converter
// Make a defensive copy of the adapters and add the default Call adapter.
List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>(this.callAdapterFactories);
callAdapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor));
// Make a defensive copy of the converters.
List<Converter.Factory> converterFactories = new ArrayList<>(1 + this.converterFactories.size());
// Add the built-in converter factory first. This prevents overriding its behavior but also
// ensures correct behavior when using converters that consume all types.
converterFactories.add(new BuiltInConverters());
converterFactories.addAll(this.converterFactories);
return new Retrofit(callFactory, baseUrl, unmodifiableList(converterFactories),
unmodifiableList(callAdapterFactories), callbackExecutor, validateEagerly);
}
}
3、Retrofit.create()
public final class Retrofit {
......
public <T> T create(final Class<T> service) {
// 校验class必须是接口,并且不能继承其他接口
Utils.validateServiceInterface(service);
// 是否提前校验方法,提前创建ServiceMethod,如果自定义的接口方法存在不合规范则抛出异常
if (validateEagerly) {
eagerlyValidateMethods(service);
}
// 返回一个代理对象,当调用api方法的时候,代理对象执行
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 {
// If the method is a method from Object then defer to normal invocation.
if (method.getDeclaringClass() == Object.class) {
return method.invoke(this, args);
}
if (platform.isDefaultMethod(method)) {
return platform.invokeDefaultMethod(method, service, proxy, args);
}
// 下面这两行是核心代码,生成ServiceMethod和请求OkHttpCall
ServiceMethod<Object, Object> serviceMethod =
(ServiceMethod<Object, Object>) loadServiceMethod(method);
OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
// 执行adapt方法,返回指定的数据类型,具体内容会在后面CallAdapter类中说明
return serviceMethod.adapt(okHttpCall);
}
});
}
......
ServiceMethod<?, ?> loadServiceMethod(Method method) {
ServiceMethod<?, ?> result = serviceMethodCache.get(method);
if (result != null) return result;
// 同步锁
synchronized (serviceMethodCache) {
// 通过method对象,获取对应缓存的ServiceMethod
result = serviceMethodCache.get(method);
if (result == null) {
// 创建ServiceMethod并存入缓存
result = new ServiceMethod.Builder<>(this, method).build();
serviceMethodCache.put(method, result);
}
}
return result;
}
......
}
到这里我们就拿到了接口代理对象对象,当调用接口具体方法api.getPersonalInfo("zhangSanLisi");
的时候就会执行invoke方法,获取创建的ServiceMethod对象,执行serviceMethod.adapt(okHttpCall)
方法,这里我们指定了请求适配器为RxJava2CallAdapter,则返回Observable。具体参见下面RxJava2CallAdapter的adapt方法
4、ServiceMethod
这是Retrofit框架核心类。ServiceMethod类功能是将自定义的接口方法解析适配成Http调用的Call,也就是生成Http请求。该类也是通过构造者模式实例化:new ServiceMethod.Builder<>(this, method).build()。
final class ServiceMethod<R, T> {
......
// 这个方法会在创建真正OkHttp请求时调用,即OkHttpCall类中createRawCall()方法
// 参见下面OkHttpCall分析里enqueue方法
okhttp3.Call toCall(@Nullable Object... args) throws IOException {
// 通过构造者模式RequestBuilder来创建请求Request
// 里面有使用到ServiceMethod生成的ParameterHandler对象,主要是解析不同的请求参数,大家可自行查看源码分析
RequestBuilder requestBuilder = new RequestBuilder(httpMethod, baseUrl, relativeUrl, headers,
contentType, hasBody, isFormEncoded, isMultipart);
@SuppressWarnings("unchecked") // It is an error to invoke a method with the wrong arg types.
ParameterHandler<Object>[] handlers = (ParameterHandler<Object>[]) parameterHandlers;
int argumentCount = args != null ? args.length : 0;
if (argumentCount != handlers.length) {
throw new IllegalArgumentException("Argument count (" + argumentCount
+ ") doesn't match expected count (" + handlers.length + ")");
}
for (int p = 0; p < argumentCount; p++) {
handlers[p].apply(requestBuilder, args[p]);
}
// 最终回通过Retrofit里面指定的callFactory执行,这里不指定时,默认是OkHttpClient,这里不做进一步分析,具体可参考OkHttp源码。
return callFactory.newCall(requestBuilder.build());
}
......
static final class Builder<T, R> {
......
Builder(Retrofit retrofit, Method method) {
this.retrofit = retrofit;
this.method = method;
// 获取方法注解, 如@POST、@Headers
this.methodAnnotations = method.getAnnotations();
// 获取方法参数类型,如String
this.parameterTypes = method.getGenericParameterTypes();
// 获取方法参数注解,如@Query
this.parameterAnnotationsArray = method.getParameterAnnotations();
}
public ServiceMethod build () {
/*
* 一系列判断之后调用的是 (CallAdapter<T, R>) retrofit.callAdapter(returnType, annotations);
* 遍历Retrofit配置时设置的callAdapterFactories,如果设置的是RxJava2CallAdapterFactory最终调用其get方法;
* 经过一系列的返回类型判断,最终返回CallAdapter,这里也就是RxJava2CallAdapter
*/
callAdapter = createCallAdapter();
// 返回类型
responseType = callAdapter.responseType();
if (responseType == Response.class || responseType == okhttp3.Response.class) {
throw methodError("'" + Utils.getRawType(responseType).getName()
+ "' is not a valid response body type. Did you mean ResponseBody?");
}
/*
* 获取转换器,也就是序列化和反序列化方式,retrofit.responseBodyConverter(responseType, annotations);
* 遍历Retrofit配置时设置的converterFactories,设置的Gson,则会调用GsonConverterFactory的responseBodyConverter方法;
* 返回GsonResponseBodyConverter类,这里将在后面响应回调分析中使用到。
*/
responseConverter = createResponseConverter();
for (Annotation annotation : methodAnnotations) {
// 遍历方法注解,这里会解析自定义接口里的方法注解并获取对应的value,为最后创建请求okhttp3.Call准备参数
parseMethodAnnotation(annotation);
}
// 是否指定了请求方式
if (httpMethod == null) {
throw methodError("HTTP method annotation is required (e.g., @GET, @POST, etc.).");
}
// 校验请求方式与编码方式是否不合理。FormUrlEncoded和Multipart这两种编码方式必须使用在有请求体的请求方式中,如:@POST,@PUT
if (!hasBody) {
if (isMultipart) {
throw methodError("Multipart can only be specified on HTTP methods with request body (e.g., @POST).");
}
if (isFormEncoded) {
throw methodError("FormUrlEncoded can only be specified on HTTP methods with "
+ "request body (e.g., @POST).");
}
}
// 下面是方法参数注解解析并获取其对应的value,方法参数类型不能是泛型和通配符
int parameterCount = parameterAnnotationsArray.length;
parameterHandlers = new ParameterHandler<?>[parameterCount];
for (int p = 0; p < parameterCount; p++) {
Type parameterType = parameterTypes[p];
if (Utils.hasUnresolvableType(parameterType)) {
throw parameterError(p, "Parameter type must not include a type variable or wildcard: %s",
parameterType);
}
Annotation[] parameterAnnotations = parameterAnnotationsArray[p];
if (parameterAnnotations == null) {
throw parameterError(p, "No Retrofit annotation found.");
}
// 这里parseParameter方法会调用到Retrofit中requestBodyConverter方法
// 即GsonRequestBodyConverter类中的convert方法,进行数据序列化。
parameterHandlers[p] = parseParameter(p, parameterType, parameterAnnotations);
}
// 下面一些是判断方法参数注解与请求方式、编码方式是否匹配或冲突
if (relativeUrl == null && !gotUrl) {
throw methodError("Missing either @%s URL or @Url parameter.", httpMethod);
}
if (!isFormEncoded && !isMultipart && !hasBody && gotBody) {
throw methodError("Non-body HTTP method cannot contain @Body.");
}
if (isFormEncoded && !gotField) {
throw methodError("Form-encoded method must contain at least one @Field.");
}
if (isMultipart && !gotPart) {
throw methodError("Multipart method must contain at least one @Part.");
}
// 最终返回ServiceMethod实例对象
return new ServiceMethod<>(this);
}
}
......
}
GsonRequestBodyConverter
final class GsonRequestBodyConverter<T> implements Converter<T, RequestBody> {
private static final MediaType MEDIA_TYPE = MediaType.parse("application/json; charset=UTF-8");
private static final Charset UTF_8 = Charset.forName("UTF-8");
private final Gson gson;
private final TypeAdapter<T> adapter;
GsonRequestBodyConverter(Gson gson, TypeAdapter<T> adapter) {
this.gson = gson;
this.adapter = adapter;
}
@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());
}
}
5、RxJava2CallAdapter
这里根据设置生成相对应的RxJava的被观察者对象
final class RxJava2CallAdapter<R> implements CallAdapter<R, Object> {
......
@Override public Object adapt(Call<R> call) {
// 这里我们只考虑异步的情况,同步基本一致。生成CallEnqueueObservable对象,call为OkHttpCall
Observable<Response<R>> responseObservable = isAsync
? new CallEnqueueObservable<>(call)
: new CallExecuteObservable<>(call);
Observable<?> observable;
if (isResult) {
observable = new ResultObservable<>(responseObservable);
} else if (isBody) {
observable = new BodyObservable<>(responseObservable);
} else {
observable = responseObservable;
}
// 指定运行线程,RxJava2CallAdapterFactory.createWithScheduler(Scheduler)指定创建
if (scheduler != null) {
observable = observable.subscribeOn(scheduler);
}
if (isFlowable) {
return observable.toFlowable(BackpressureStrategy.LATEST);
}
if (isSingle) {
return observable.singleOrError();
}
if (isMaybe) {
return observable.singleElement();
}
if (isCompletable) {
return observable.ignoreElements();
}
return observable;
}
}
6、CallEnqueueObservable
RxJava的方法调用,当被观察者调用.subscribe()
订阅之后,会调用到里面的subscribeActual()
方法。
final class CallEnqueueObservable<T> extends Observable<Response<T>> {
......
@Override protected void subscribeActual(Observer<? super Response<T>> observer) {
// Since Call is a one-shot type, clone it for each new observer.
Call<T> call = originalCall.clone();
retrofit2.adapter.rxjava2.CallEnqueueObservable.CallCallback<T> callback = new retrofit2.adapter.rxjava2.CallEnqueueObservable.CallCallback<>(call, observer);
observer.onSubscribe(callback);
// 这里是将call加入队列,并传入下面的CallCallback对象,异步请求。前面我们说过这歌call对象是OkHttpCall。
call.enqueue(callback);
}
private static final class CallCallback<T> implements Disposable, Callback<T> {
......
//下面是正确和失败回调,即调用onNext和onError方法
@Override public void onResponse(Call<T> call, Response<T> response) {
if (disposed) return;
try {
observer.onNext(response);
if (!disposed) {
terminated = true;
observer.onComplete();
}
} catch (Throwable t) {
......
}
}
@Override public void onFailure(Call<T> call, Throwable t) {
if (call.isCanceled()) return;
try {
observer.onError(t);
} catch (Throwable inner) {
......
}
}
}
}
7、OkHttpCall
上面call.enqueue(callback)
实际走的就是OkHttpCall的enqueue方法。
final class OkHttpCall<T> implements Call<T> {
......
@Override
public void enqueue(final Callback<T> callback) {
// 回调非空判断
checkNotNull(callback, "callback == null");
okhttp3.Call call;
Throwable failure;
// 同步锁,创建真正发起网络请求的okhttp3.Call,会ServiceMethod类里toCall方法
synchronized (this) {
// 这里会对请求是否执行过判断,也就是说代理对象方法里生成的OkHttpCall只能执行一次
if (executed) throw new IllegalStateException("Already executed.");
executed = true;
call = rawCall;
failure = creationFailure;
if (call == null && failure == null) {
try {
call = rawCall = createRawCall();
} catch (Throwable t) {
throwIfFatal(t);
failure = creationFailure = t;
}
}
}
if (failure != null) {
callback.onFailure(this, failure);
return;
}
if (canceled) {
call.cancel();
}
// 这里就转到了OkHttp网络请求框架,加入到请求队列里面。
// 最后回调回调用CallEnqueueObservable中的CallCallback,即onNext或onError方法
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(retrofit2.OkHttpCall.this, response);
} catch (Throwable t) {
t.printStackTrace();
}
}
@Override
public void onFailure(okhttp3.Call call, IOException e) {
callFailure(e);
}
private void callFailure(Throwable e) {
try {
callback.onFailure(retrofit2.OkHttpCall.this, e);
} catch (Throwable t) {
t.printStackTrace();
}
}
});
}
......
private okhttp3.Call createRawCall() throws IOException {
// 调用的是ServiceMethod里面的toCall()方法
okhttp3.Call call = serviceMethod.toCall(args);
if (call == null) {
throw new NullPointerException("Call.Factory returned null.");
}
return call;
}
}
下面我们看下异步请求的回调,这里只分析成功回调,失败回调是一样的。
在上面enqueue方法回调中有parseResponse(rawResponse)
这么一行代码,它做的就是解析响应数据的功能。
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);
}
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;
}
}
ServiceMethod类中toResponse方法:
R toResponse(ResponseBody body) throws IOException {
return responseConverter.convert(body);
}
这里直接分析核心代码T body = serviceMethod.toResponse(catchingBody);
,通过源码可以看到,最终其调用的是Retrofit配置时设置的converterFactories类的convert方法,返回设定的对象,即反序列化响应数据。
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;
}
@Override public T convert(ResponseBody value) throws IOException {
JsonReader jsonReader = gson.newJsonReader(value.charStream());
try {
T result = adapter.read(jsonReader);
if (jsonReader.peek() != JsonToken.END_DOCUMENT) {
throw new JsonIOException("JSON document was not fully consumed.");
}
return result;
} finally {
value.close();
}
}
}
8、ExecutorCallAdapterFactory
如果我们没有添加CallAdapterFactory请求适配器,则会使用Android平台默认请求适配器ExecutorCallAdapterFactory,调用enqueue方法时会走ExecutorCallbackCall中的enqueue方法,然后执行OkHttpCall的enqueue方法,代码如下:
@Override public void enqueue(final Callback<T> callback) {
checkNotNull(callback, "callback == null");
// 这里的delegate就是OkHttpCall,最终还是走到OkHttpCall的enqueue方法
delegate.enqueue(new Callback<T>() {
@Override public void onResponse(Call<T> call, final Response<T> response) {
callbackExecutor.execute(new Runnable() {
@Override public void run() {
if (delegate.isCanceled()) {
// Emulate OkHttp's behavior of throwing/delivering an IOException on cancellation.
callback.onFailure(ExecutorCallAdapterFactory.ExecutorCallbackCall.this, new IOException("Canceled"));
} else {
callback.onResponse(ExecutorCallAdapterFactory.ExecutorCallbackCall.this, response);
}
}
});
}
@Override public void onFailure(Call<T> call, final Throwable t) {
callbackExecutor.execute(new Runnable() {
@Override public void run() {
callback.onFailure(ExecutorCallAdapterFactory.ExecutorCallbackCall.this, t);
}
});
}
});
}
9、BuiltInConverters
如果没有添加ConverterFactory,则会使用默认的BuiltInConverters进行requestBody序列化和responseBody反序列化。当然,在BuiltInConverters还存在一个重要的类ToStringConverter,不管有没有额外添加ConverterFactory,其在ServiceMethod进行注解解析时都会使用到,具体参见ServiceMethod类中的ParameterHandler<?> parseParameterAnnotation( int p, Type type, Annotation[] annotations, Annotation annotation)
方法。
final class BuiltInConverters extends Converter.Factory {
// 响应数据反序列化转换器
@Override
public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations,
Retrofit retrofit) {
// 根据要求响应数据类型的不同,返回不同的converter
if (type == ResponseBody.class) {
return Utils.isAnnotationPresent(annotations, Streaming.class)
? retrofit2.BuiltInConverters.StreamingResponseBodyConverter.INSTANCE
: retrofit2.BuiltInConverters.BufferingResponseBodyConverter.INSTANCE;
}
if (type == Void.class) {
return retrofit2.BuiltInConverters.VoidResponseBodyConverter.INSTANCE;
}
return null;
}
// 请求体数据序列化转化器
@Override
public Converter<?, RequestBody> requestBodyConverter(Type type,Annotation[] parameterAnnotations,
Annotation[] methodAnnotations, Retrofit retrofit) {
if (RequestBody.class.isAssignableFrom(Utils.getRawType(type))) {
return retrofit2.BuiltInConverters.RequestBodyConverter.INSTANCE;
}
return null;
}
static final class VoidResponseBodyConverter implements Converter<ResponseBody, Void> {
static final retrofit2.BuiltInConverters.VoidResponseBodyConverter
INSTANCE = new retrofit2.BuiltInConverters.VoidResponseBodyConverter();
@Override public Void convert(ResponseBody value) {
// 不需要返回,直接close,返回null
value.close();
return null;
}
}
// RequestBody请求体转换器
static final class RequestBodyConverter implements Converter<RequestBody, RequestBody> {
static final retrofit2.BuiltInConverters.RequestBodyConverter
INSTANCE = new retrofit2.BuiltInConverters.RequestBodyConverter();
@Override public RequestBody convert(RequestBody value) {
return value;
}
}
// 流转换器
static final class StreamingResponseBodyConverter
implements Converter<ResponseBody, ResponseBody> {
static final retrofit2.BuiltInConverters.StreamingResponseBodyConverter
INSTANCE = new retrofit2.BuiltInConverters.StreamingResponseBodyConverter();
@Override public ResponseBody convert(ResponseBody value) {
return value;
}
}
// 容器转换器
static final class BufferingResponseBodyConverter
implements Converter<ResponseBody, ResponseBody> {
static final retrofit2.BuiltInConverters.BufferingResponseBodyConverter
INSTANCE = new retrofit2.BuiltInConverters.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();
}
}
}
// 转换成String
static final class ToStringConverter implements Converter<Object, String> {
static final retrofit2.BuiltInConverters.ToStringConverter
INSTANCE = new retrofit2.BuiltInConverters.ToStringConverter();
@Override public String convert(Object value) {
return value.toString();
}
}
}
注意事项
通过源码的分析,发现一些特别需要注意的事项:
1、必须指定一个请求方式,并且不能设置两个或两个以上,请求方式有:@POST、@GET、@DELETE、@HEAD、@PATCH、@PUT、@OPTIONS、@HTTP;
2、Retrofit配置时设置的baseUrl与设置请求方式对应的relativeUrl,结合后要是一个合理的url,不能同时relativeUrl为null,而又不添加@Url;
3、返回数据类型不能是Retrofit中的Response
或okhttp3.Response
;
4、请求过程中生成OkHttpCall
对象,只能调用一次请求,不能重复调用;
5、默认响应数据返回ResponseBody
, 请求体@Body
可使用RequestBody
,当使用自定义实体bean时,不管做为@Body值还是作为响应数据类型都必须添加一个ConverterFactory,如常用的GsonConverterFactory
;
6、注解的使用不能胡乱搭配,比如:@Multipart和@isFormEncoded与@GET等没有请求体的请求方式一起使用,再者添加了@Multipart,在参数里面必须要有@Part注解。具体的可以分析ServiceMethod类中的parseParameterAnnotation
方法。
总结
这次分析以Retrofit使用流程为主线,熟悉Retrofit的工作机制以及一些注意事项。Retrofit中使用了几种设计模式:构造者模式(Builder)、工厂模式(Factory)、策略模式(不同的CallAdapter和Converter)、观察者模式等等,这些都是在以后的工作中可以值得借鉴的地方。还有就是注解的使用,这是一个很好的范例,基本上注解使用和解析的相关知识全部都涉及到了,可以阅读一下文章开始推荐的Java-Type体系,是两篇值得一读好文章。
以上就是本次分析的全部内容,由于个人能力有限,如有不足或错误的地方,敬请谅解。
网友评论