您的位置:首页 > 移动开发 > Android开发

Retrofit2 源码分析

2016-07-22 16:54 399 查看

什么是Retrofit

A type-safe HTTP client for Android and Java

一款在Java和Android平台上使用的类型安全的Http客户端

Retrofit的特点

将API请求转化为接口,具体的接口方法代替各个API

使用注解标记请求方法类型、参数类型

支持Multipart和文件上传

将返回结果转化为对象,并可自定义数据转化器

提供异步请求方式

可自定义网络客户端okHttpClient、HttpClient

关键步骤

请求解析

请求封装

请求异步处理

请求结果转换

源码分析

关键代码: T create(final Class service) 这个方法包含了上述流程中的请求解析和封装。

public <T> T create(final Class<T> service) {
//检查接口类的合法性:1、必须是接口类型。2、不能继承其他接口。
Utils.validateServiceInterface(service);
if (validateEagerly) {
//如果需要提前验证接口方法,则走此逻辑。
//遍历接口中的方法Method,并包装成ServiceMethod,缓存到LinkedHashMap中
eagerlyValidateMethods(service);
}
//使用Java动态代理生成接口具体对象。并封装成ServiceMethod--->OkHttpCall
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, 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);
}
//上面部分可以忽略,如果是Object或平台自带的方法,不进行代理。
//如果是我们在接口中声明的方法,则构造一个ServiceMethod对象,相当于请求解析。然后根据ServiceMethod和参数构造一个OkHttpCall,相当于请求封装。
//最后一句,serviceMethod.callAdapter就是Retrofit里面指定的CallAdapter。CallAdapter的作用是将一个请求转化成AdapterFactory要求的返回类型。
//如果没有自定义返回类型,Retrofit会使用默认的ExecutorCallAdapterFactory
//Retrofit2执行接口请求时会返回一个Call<T>对象,当调用Call<T>的enqueue或execute方法时,才会真正去请求。
ServiceMethod serviceMethod = loadServiceMethod(method);
OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args);
return serviceMethod.callAdapter.adapt(okHttpCall);
}
});
}


1.请求解析

Retrofit的请求解析是通过ServiceMethod这个类完成,将一个接口方法转换成一个HTTP请求。具体的解析过程很繁杂,但是很简单。无非就是取到接口方法的各类注解,然后分别

解析请求类型(parseMethodAnnotation(Annotation anotattion))

解析参数(parseParameter(int p, Type parameterType, Annotation[] annotations))

创建CallAdapter (retrofit.callAdapter(returnType, annotations))

创建ResponseConverter(retrofit.responseBodyConverter(responseType, annotations))

解析完成后,调用ServiceMethod的构造方法new ServiceMethod<>(this);

构造方法如下

ServiceMethod类的构造也是通过Builder模式实现的,下面一一介绍一下ServiceMethod中全局变量的含义。
ServiceMethod(Builder<T> builder) {
//Http请求创建工厂,在创建Retrofit对象时指定,类型为okhttp3.Call.Factory,默认的是OkHttpClient
this.callFactory = builder.retrofit.callFactory();
//请求适配器,将请求结果转换成指定类型Call<T>
this.callAdapter = builder.callAdapter;
//网络请求基础域名地址,可在创建Retrofit对象时指定,也可以通过@URL注解指定
this.baseUrl = builder.retrofit.baseUrl();
//请求结果转化器
this.responseConverter = builder.responseConverter;
//Http请求类型 String类型,如“GET”/“POST”
this.httpMethod = builder.httpMethod;
//接口相对地址
this.relativeUrl = builder.relativeUrl;
//请求头信息 Retrofit支持为某个接口单独设置请求头
this.headers = builder.headers;
//内容类型即请求头中设置Content-Type的值
this.contentType = builder.contentType;
//是否包含请求体,Post和Put请求是由请求体的
this.hasBody = builder.hasBody;
//是否使用表单编码格式,当存在@FormUrlEncoded注解,此字段为true
this.isFormEncoded = builder.isFormEncoded;
//是否是多部件上传,当存在@MuitlPart注解时,此字段为true
this.isMultipart = builder.isMultipart;
//参数注解列表,即由注解指定的参数名称列表。如@Filed("id")
this.parameterHandlers = builder.parameterHandlers;
}


除了构造方法,还有两个比较重要的方法 toRequest(Object … args)和toResponse(ResponseBody body)。他们分别使用当前ServiceMethod存储的请求方法信息,生成一个真正的Http请求和自定义解析后的响应。

请求封装

/** Builds an HTTP request from method arguments. */
Request toRequest(Object... args) throws IOException {
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]);
}

return requestBuilder.build();
}

/** Builds a method return value from an HTTP response body. */
T toResponse(ResponseBody body) throws IOException {
return responseConverter.convert(body);
}


请求异步、同步处理

Retrofit2中同步、异步请求是由okHttp3.Call实现的。

异步请求

call.enqueue(new okhttp3.Callback() {
@Override public void onResponse(okhttp3.Call call, okhttp3.Response rawResponse)
throws IOException {
Response<T> response;
try {
response = parseResponse(rawResponse);
} catch (Throwable e) {
callFailure(e);
return;
}
callSuccess(response);
}

@Override public void onFailure(okhttp3.Call call, IOException e) {
try {
callback.onFailure(OkHttpCall.this, e);
} catch (Throwable t) {
t.printStackTrace();
}
}

private void callFailure(Throwable e) {
try {
callback.onFailure(OkHttpCall.this, e);
} catch (Throwable t) {
t.printStackTrace();
}
}

private void callSuccess(Response<T> response) {
try {
//请求成功后,通过回调CallBack将结果回传给调用者
callback.onResponse(OkHttpCall.this, response);
} catch (Throwable t) {
t.printStackTrace();
}
}
});


同步请求

@Override public Response<T> execute() throws IOException {
okhttp3.Call call;

synchronized (this) {
if (executed) throw new IllegalStateException("Already executed.");
executed = true;

if (creationFailure != null) {
if (creationFailure instanceof IOException) {
throw (IOException) creationFailure;
} else {
throw (RuntimeException) creationFailure;
}
}

call = rawCall;
if (call == null) {
try {
call = rawCall = createRawCall();
} catch (IOException | RuntimeException e) {
creationFailure = e;
throw e;
}
}
}

if (canceled) {
call.cancel();
}

return parseResponse(call.execute());
}


请求结果转换

当请求结束后,会调用parseResponse(okhttp3.Response 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) {
return Response.success(null, rawResponse);
}

ExceptionCatchingRequestBody catchingBody = new ExceptionCatchingRequestBody(rawBody);
try {
//此处将返回结果交由用户指定或Retrofit默认的Converter进行数据转换。默认的转换器有StreamingResponseBodyConverter、BufferingResponseBodyConverter、ToStringConverter等。
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;
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  android Retrofit