整体结构
Retrofit通过动态代理的方式,将我们声明的interface转换成一个请求,
通过静态代理,将我们去请求交给okhttpclient去执行。
使用方法
Retrofit.Builder builder = new Retrofit.Builder();
builder.baseUrl("https://github.com/");
builder.addConverterFactory(GsonConverterFactory.create());
builder.addConverterFactory(GsonConverterFactory.create());
Retrofit build = builder.build();
GitInterfae gitInterfae = build.create(GitInterfae.class);
Call<List<String>> azewz = gitInterfae.listRepos("azewz");
azewz.enqueue(new Callback<List<String>>() {
@Override
public void onResponse(Call<List<String>> call, Response<List<String>> response) {
Log.i("TAG","请求成功");
}
@Override
public void onFailure(Call<List<String>> call, Throwable t) {
Log.i("TAG", "请求失败");
}
});
- 构件Buidler
确定平台
Builder初始化一个内建的Converters
- 设定baseURL
- build.create(API.class); 构件一个OkHttp中call的静态代理
- 执行Call的实例,实际是调用OkHttp的call类
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);
}
ServiceMethod serviceMethod = loadServiceMethod(method);
OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args);
return serviceMethod.callAdapter.adapt(okHttpCall);
}
});
}
- 当 Call<List<String>> azewz = gitInterfae.listRepos("azewz");就会执行动态代理中的handler的invoke,进行执行。
loadServiceMethod将接口中声明的方法转换成我们一个ServiceMethod实例,包含了CallAdapter,RespenseConvert和请求的所有信息,例如http的头信息,参数信息等。这里会有一
个缓存,当改方法已经被实例化成ServiceMethod,将可以直接重缓存mapserviceMethodCache
中取出。
OKHttpCall就是okhttp的静态代理类。
当执行enqueue时,才发起请求。 - 当请求结果完成后,在OkHttpCall,使用parseResponse()解析返回的数据
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 {
T body = serviceMethod.toResponse(catchingBody); //调用我们的Convert类的转换方法,
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;
}
}
204 No Content
服务器成功处理了请求,但不需要返回任何实体内容,并且希望返回更新了的元信息。响应可能通过实体头部的形式,返回新的或更新后的元信息。如果存在这些头部信息,则应当与所请求的变量相呼应。
如果客户端是浏览器的话,那么用户浏览器应保留发送了该请求的页面,而不产生任何文档视图上的变化,即使按照规范新的或更新后的元信息应当被应用到用户浏览器活动视图中的文档。
由于204响应被禁止包含任何消息体,因此它始终以消息头后的第一个空行结尾。
205 Reset Content
服务器成功处理了请求,且没有返回任何内容。但是与204响应不同,返回此状态码的响应要求请求者重置文档视图。该响应主要是被用于接受用户输入后,立即重置表单,以便用户能够轻松地开始另一次输入。
与204响应一样,该响应也被禁止包含任何消息体,且以消息头后的第一个空行结束。
自定义Convert
继承 extends Converter.Factory
final class JacksonResponseBodyConverter<T> implements Converter<ResponseBody, T>
final class JacksonRequestBodyConverter<T> implements Converter<T, RequestBody>