几个核心的类
- Retrofit,入口类
- Call,请求接口类
- CallAdapter,Call适配器,可以将Call转换为其他的类实例,比如,在与Rxjava一起使用的时候,将Call转换为Observable
- Converter,request和response的转换类
- ServiceMethod,个人感觉是最核心的实现类,request、response的各种转换都是在这里执行的
- OkHttpCall,Call的默认实现类
基本使用
public interface DemoHttpService {
@POST()
Call<ResponseBody> post(@Url String url, @HeaderMap Map<String, String> header, @Body RequestBody body);
}
new Retrofit.builder().baseUrl("https://xxx.xxx").build().create(DemoHttpService.class).post("/yyy/zzz", map, body).execute()
根据使用流程分析代码
这里主要分析各个类的作用,所以各个类均使用默认实现
new Retrofit.builder().build()
public Retrofit build() {
// 默认情况下,主要的几个成员变量
// callFactory = new OkHttpClient();
// adapterFactories 仅包含 ExecutorCallAdapterFactory
// converterFactories 仅包含 BuiltInConverters
}
Retrofit.create(DemoHttpService.class).post(//…)
通过动态代理返回 T,也就是上面DemoHttpService中的Call
public <T> T create(final Class<T> service) {
// ...
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 {
// ...
ServiceMethod<Object, Object> serviceMethod =
(ServiceMethod<Object, Object>) loadServiceMethod(method);
OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
return serviceMethod.callAdapter.adapt(okHttpCall);
}
});
}
生成的动态代理主要做3步
- 获取ServiceMethod实例
- 创建OkHttpCall实例
- 使用CallAdapter调用OkHttpCall
分别看一下
获取ServiceMethod实例
// loadServiceMethod,即调用new ServiceMethod.Builder<>(this, method).build()构造ServiceMethod实例
// 其中this是Retrofit类的实例,method是自定义的service中的方法
Builder(Retrofit retrofit, Method method) {
this.retrofit = retrofit; // Retrofit实例
this.method = method; // method实例
this.methodAnnotations = method.getAnnotations(); // 方法的注解,以上面的DemoHttpService为例,即"POST"
this.parameterTypes = method.getGenericParameterTypes(); // 方法参数的类型,以上面的DemoHttpService为例,即String, Map, RequestBody
this.parameterAnnotationsArray = method.getParameterAnnotations(); // 方法参数的注解,以上面的DemoHttpService为例,即Url, HeaderMap, Body
}
public ServiceMethod build() {
// 1. 创建CallAdapter
callAdapter = createCallAdapter();
responseType = callAdapter.responseType();
if (responseType == Response.class || responseType == okhttp3.Response.class) {
// ...
}
// 2. 创建ResponseConverter
responseConverter = createResponseConverter();
// 3. 解析方法的注解,HTTP method 如@GET, @POST等
for (Annotation annotation : methodAnnotations) {
parseMethodAnnotation(annotation);
}
// ...
// 4. 解析请求参数
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.");
}
parameterHandlers[p] = parseParameter(p, parameterType, parameterAnnotations);
}
// ...
return new ServiceMethod<>(this);
}
主要分为4步
1. 创建CallAdapter
2. 创建ResponseConverter
3. 解析方法的注解,HTTP method 如@GET, @POST等
4. 解析请求参数
分别看一下
创建CallAdapter
// 最后调用的是Retrofit.nextCallAdapter
public CallAdapter<?, ?> nextCallAdapter(@Nullable CallAdapter.Factory skipPast, Type returnType,
Annotation[] annotations) {
// ...
int start = adapterFactories.indexOf(skipPast) + 1;
for (int i = start, count = adapterFactories.size(); i < count; i++) {
CallAdapter<?, ?> adapter = adapterFactories.get(i).get(returnType, annotations, this);
if (adapter != null) {
return adapter;
}
}
// ...
}
// 即调用到adapterFactories的get方法,如果没有设置自定义的factory的话,就是调用DefaultCallAdapterFactory
// 返回的就是一个CallAdapter实例
public CallAdapter<?, ?> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
if (getRawType(returnType) != Call.class) {
return null;
}
final Type responseType = Utils.getCallResponseType(returnType);
return new CallAdapter<Object, Call<?>>() {
@Override public Type responseType() {
return responseType;
}
@Override public Call<Object> adapt(Call<Object> call) {
return call;
}
};
}
创建ResponseConverter
// 创建ResponseConverter也是一样的,调用到Retrofit.nextResponseBodyConverter,默认的是Convert.Factory
// 实例是BuiltInConverters
public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations,
Retrofit retrofit) {
// 以DemoHttpService为例,annotations是POST,所以这里返回BufferingResponseBodyConverter.INSTANCE
if (type == ResponseBody.class) {
return Utils.isAnnotationPresent(annotations, Streaming.class)
? StreamingResponseBodyConverter.INSTANCE
: BufferingResponseBodyConverter.INSTANCE;
}
if (type == Void.class) {
return VoidResponseBodyConverter.INSTANCE;
}
return null;
}
解析方法的注解,HTTP method 如@GET, @POST等
// DemoHttpService中,只有POST,没有带查询参数,调用之后,只是对httpMethod和hasBody赋值
// 如果有参数的话,会再进行解析
private void parseHttpMethodAndPath(String httpMethod, String value, boolean hasBody) {
if (this.httpMethod != null) {
throw methodError("Only one HTTP method is allowed. Found: %s and %s.",
this.httpMethod, httpMethod);
}
this.httpMethod = httpMethod;
this.hasBody = hasBody;
if (value.isEmpty()) {
return;
}
// Get the relative URL path and existing query string, if present.
int question = value.indexOf('?');
if (question != -1 && question < value.length() - 1) {
// Ensure the query string does not have any named parameters.
String queryParams = value.substring(question + 1);
Matcher queryParamMatcher = PARAM_URL_REGEX.matcher(queryParams);
if (queryParamMatcher.find()) {
throw methodError("URL query string \"%s\" must not have replace block. "
+ "For dynamic query parameters use @Query.", queryParams);
}
}
this.relativeUrl = value;
this.relativeUrlParamNames = parsePathParameters(value);
}
解析请求参数
// DemoHttpService.post方法中的每个参数调用parseParameter
// 这个方法主要就是些if...else...分支,根据注解的不同,创建不同的ParameterHandler实现类的实例
// ParameterHandler这个接口包含一个方法
// apply(RequestBuilder builder, @Nullable T value) -- 用请求参数构造RequestBuilder,会在实际发送请求前构造
// 实现类有如下这些
ParameterHandler (retrofit2)
HeaderMap in ParameterHandler (retrofit2)
Body in ParameterHandler (retrofit2)
RawPart in ParameterHandler (retrofit2)
FieldMap in ParameterHandler (retrofit2)
QueryName in ParameterHandler (retrofit2)
QueryMap in ParameterHandler (retrofit2)
Path in ParameterHandler (retrofit2)
Query in ParameterHandler (retrofit2)
RelativeUrl in ParameterHandler (retrofit2)
PartMap in ParameterHandler (retrofit2)
Part in ParameterHandler (retrofit2)
Field in ParameterHandler (retrofit2)
Header in ParameterHandler (retrofit2)
针对上面的例子,解析参数之后,会创建3个对象,对应post方法的三个入参
parameterHandlers = {ParameterHandler[3]@6440}
0 = {ParameterHandler$RelativeUrl@6568}
1 = {ParameterHandler$HeaderMap@6539}
2 = {ParameterHandler$Body@6569}
创建okHttp实例
这一步很简单
OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
创建Call实例
// 创建ServiceMethod.callAdapter时,用的默认实现,也就是ExecutorCallAdapterFactory
// 所以return serviceMethod.callAdapter.adapt(okHttpCall);执行的就是ExecutorCallAdapterFactory.get.adapte
// 返回的就是ExecutorCallbackCall实例
public CallAdapter<?, ?> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
if (getRawType(returnType) != Call.class) {
return null;
}
final Type responseType = Utils.getCallResponseType(returnType);
return new CallAdapter<Object, Call<?>>() {
@Override public Type responseType() {
return responseType;
}
@Override public Call<Object> adapt(Call<Object> call) {
return new ExecutorCallbackCall<>(callbackExecutor, call);
}
};
}
执行请求
通过Retrofit.create(DemoHttpService.class).post(// …)之后,得到了ExecutorCallbackCall实例,
接下来执行execute或者enqueue来发起同步/异步请求,实际执行的就是OkHttpCall。
以OkHttpCall.execute为例
@Override public Response<T> execute() throws IOException {
okhttp3.Call call;
synchronized (this) {
// ...
call = rawCall;
if (call == null) {
try {
// 1. 首先创建OkHttp3.Call
call = rawCall = createRawCall();
} catch (IOException | RuntimeException e) {
// ...
}
}
}
if (canceled) {
call.cancel();
}
// 2. 执行请求解析
return parseResponse(call.execute());
}
- 创建OkHttp3.创建Call实例
private okhttp3.Call createRawCall() throws IOException {
Request request = serviceMethod.toRequest(args);
okhttp3.Call call = serviceMethod.callFactory.newCall(request);
if (call == null) {
throw new NullPointerException("Call.Factory returned null.");
}
return call;
}
Request toRequest(@Nullable Object... args) throws IOException {
// 1. 创建RequestBuilder实例
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 + ")");
}
// 2. 用servicMethod里创建的ParameterHandler解析参数
for (int p = 0; p < argumentCount; p++) {
handlers[p].apply(requestBuilder, args[p]);
}
// 3. 调用Okhttp3.Request.Builder创建Reqeust
return requestBuilder.build();
}
- 执行请求并解析
这一步流程比较简单,解析响应并返回
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 {
// 调用serviceMethod里的responseConverter解析请求
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;
}
}
总结
- 以上是最简单的用法,retrofit里面还有其他注解可以使用,很灵活
- retrofit设计比较好的地方,个人认为是设计了多个Factory,可以用自定义的factory创建adapter/converter,比如跟com.squareup.retrofit2:adapter-rxjava和com.squareup.retrofit2:converter-jackson一起使用,除了squareup提供的,也可以自己再写其他的