Retrofit基本介绍
Retrofit是Square开源的一个适用于Android和Java的类型安全的HTTP网络框架。其本质是对OKHttp的进一步封装,通过接口的方式进行网络请求,结合了注解、动态代理等技术实现模块解耦,简化了网络请求的上层逻辑。从Android4.4开始,http的底层实现已替换成了OKHttp,Retrofit也因此成为了Android平台上主流的网络框架之一。
http://square.github.io/retro...
Retrofit使用方法
Step1:声明Retrofit API请求接口
public interface GitHub {
@GET("/repos/{owner}/{repo}/contributors")
Call<List<Contributor>> contributors(
@Path("owner") String owner,
@Path("repo") String repo);
}
- 请求类型:以@GET/POST/PUT/DELETE注解声明
- 请求相对URL:以请求方法注解内的Value值表示
- 请求参数:以接口方法@Path参数表示
Step2:构建Retrofit对象并创建API接口实例
// Create a very simple REST adapter which points the GitHub API.
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://api.github.com")
.addConverterFactory(GsonConverterFactory.create())
.build();
// Create an instance of our GitHub API interface.
GitHub github = retrofit.create(GitHub.class);
- 通过baseUrl接口声明接口请求域名;
- 配置对象的序列化和反序列化转换工厂;
Step3:通过API接口方法创建Call实例并发起请求
// Create a call instance for looking up Retrofit contributors.
Call<List<Contributor>> call = github.contributors("square", "retrofit");
// Fetch and print a list of the contributors to the library.
List<Contributor> contributors = call.execute().body();
Retrofit的实现就是这么简单优雅,业务层只需要像调用普通接口一样即可完成网络请求。
Retrofit源码解析
首先要构建一个Retrofit实例,其作用是把接口方法注解转换为OKHttp请求。
Retrofit.Builder.build
public Retrofit build() {
if (baseUrl == null) {
throw new IllegalStateException("Base URL required.");
}
okhttp3.Call.Factory callFactory = this.callFactory;
if (callFactory == null) {
callFactory = new OkHttpClient();
}
Executor callbackExecutor = this.callbackExecutor;
if (callbackExecutor == null) {
callbackExecutor = platform.defaultCallbackExecutor();
}
// 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);
}
}
- callFactory,生产并处理请求的工厂(默认创建OKHttpClient)
- callbackExecutor,用以处理callback线程调度(Android默认回调到主线程)
- callAdapterFactories,用以生产CallAdapter以处理Response类型转换(默认使用ExecutorCallAdapterFactory)
- converterFactories,用以生产Converter处理http请求响应的数据转换(默认使用BuiltInConverters)
Retrofit实例化完成,创建API接口动态代理实现。
Retrofit.create
public <T> T create(final Class<T> service) {
Utils.validateServiceInterface(service);
if (validateEagerly) {
eagerlyValidateMethods(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 {
// 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<Object, Object> serviceMethod =
(ServiceMethod<Object, Object>) loadServiceMethod(method);
OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
return serviceMethod.adapt(okHttpCall);
}
});
}
- serviceMethod,负责把接口方法注解转换为http表示(包括httpMethod/header/body/url等)
- okHttpCall,负责把serviceMethod转换为okhttp3.Call,并且包装了okhttp3.Call的接口调用。
- serviceMethod.adapt:负责把OKHttpCall转为ExecutorCallbackCall,使其具备线程调度能力。
接口动态代理创建完成,开始执行网络请求。
OKHttpCall.execute
@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 if (creationFailure instanceof RuntimeException) {
throw (RuntimeException) creationFailure;
} else {
throw (Error) creationFailure;
}
}
call = rawCall;
if (call == null) {
try {
call = rawCall = createRawCall();
} catch (IOException | RuntimeException | Error e) {
throwIfFatal(e); // Do not assign a fatal error to creationFailure.
creationFailure = e;
throw e;
}
}
}
if (canceled) {
call.cancel();
}
return parseResponse(call.execute());
}
ExecutorCallbackCall把网络请求委派给OKHttpCall,后者主要负责:
- 把接口注解参数转换为okhttp3.Call原始请求
- 执行okhttp3.Call接口请求,获取Response结果
- 把ResponseBody转换为接口返回数据类型并回调
1. ServiceMethod.toCall负责将注解参数转换为okhttp3.Call
/** Builds an HTTP request from method arguments. */
okhttp3.Call toCall(@Nullable 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 callFactory.newCall(requestBuilder.build());
}
2. OkHttpCall.parseResponse负责Response解析及请求结果状态的封装回调。
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;
}
}
3. ServiceMethod.toResponse负责将ResponseBody转换为接口返回数据类型。
*其内部Converter接口负责把HTTP请求响应结果转换可识别的数据格式。举个栗子:*
- VoidResponseBodyConverter:不做处理,直接返回RequestBody
- GsonResponseBodyConverter:将字节流转换为Java对象
- ToStringConverter:将RequestBody转换为String
/** Builds a method return value from an HTTP response body. */
R toResponse(ResponseBody body) throws IOException {
return responseConverter.convert(body);
}
ExecutorCallbackCall.execute同步请求完之后,直接取出responseConverter转换出来的body即为请求结果。
// Fetch and print a list of the contributors to the library.
List<Contributor> contributors = call.execute().body();
到此,一个Retrofit GET同步请求流程基本分析完了。想要加深理解,Read the fucking source code!
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。