怎么使用就不详述了,我们主要来看原理。
- 得到retrofit对象
我们首先通过建造者模式获得retrofit实例
Builder(Platform platform) {
this.platform = platform;
// 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());
}
public Builder() {
this(Platform.get());
}
public Builder baseUrl(HttpUrl baseUrl) {
checkNotNull(baseUrl, "baseUrl == null");
List<String> pathSegments = baseUrl.pathSegments();
if (!"".equals(pathSegments.get(pathSegments.size() - 1))) {
throw new IllegalArgumentException("baseUrl must end in /: " + baseUrl);
}
this.baseUrl = baseUrl;
return this;
}
/** Add converter factory for serialization and deserialization of objects. */
public Builder addConverterFactory(Converter.Factory factory) {
converterFactories.add(checkNotNull(factory, "factory == null"));
return this;
}
public Builder client(OkHttpClient client) {
return callFactory(checkNotNull(client, "client == null"));
}
/**
* Add a call adapter factory for supporting service method return types other than {@link
* Call}.
*/
public Builder addCallAdapterFactory(CallAdapter.Factory factory) {
adapterFactories.add(checkNotNull(factory, "factory == null"));
return this;
}
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> adapterFactories = new ArrayList<>(this.adapterFactories);
adapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor));
// Make a defensive copy of the converters.
List<Converter.Factory> converterFactories = new ArrayList<>(this.converterFactories);
return new Retrofit(callFactory, baseUrl, converterFactories, adapterFactories,
callbackExecutor, validateEagerly);
}
}
}
在构造器中,首先获得当前设备的的平台信息,并把内置的BuiltInConverters添加到工厂集合,主要作用是使用多种converters时能够找到可以消耗该类型的转化器;
我们来看Platform这个类:
class Platform {
private static final Platform PLATFORM = findPlatform();
static Platform get() {
return PLATFORM;
}
private static Platform findPlatform() {
try {
Class.forName("android.os.Build");
if (Build.VERSION.SDK_INT != 0) {
return new Android();
}
} catch (ClassNotFoundException ignored) {
}
try {
Class.forName("java.util.Optional");
return new Java8();
} catch (ClassNotFoundException ignored) {
}
try {
Class.forName("org.robovm.apple.foundation.NSObject");
return new IOS();
} catch (ClassNotFoundException ignored) {
}
return new Platform();
}
Executor defaultCallbackExecutor() {
return null;
}
CallAdapter.Factory defaultCallAdapterFactory(Executor callbackExecutor) {
if (callbackExecutor != null) {
return new ExecutorCallAdapterFactory(callbackExecutor);
}
return DefaultCallAdapterFactory.INSTANCE;
}
boolean isDefaultMethod(Method method) {
return false;
}
Object invokeDefaultMethod(Method method, Class<?> declaringClass, Object object, Object... args)
throws Throwable {
throw new UnsupportedOperationException();
}
@IgnoreJRERequirement // Only classloaded and used on Java 8.
static class Java8 extends Platform {
@Override boolean isDefaultMethod(Method method) {
return method.isDefault();
}
@Override Object invokeDefaultMethod(Method method, Class<?> declaringClass, Object object,
Object... args) throws Throwable {
// Because the service interface might not be public, we need to use a MethodHandle lookup
// that ignores the visibility of the declaringClass.
Constructor<Lookup> constructor = Lookup.class.getDeclaredConstructor(Class.class, int.class);
constructor.setAccessible(true);
return constructor.newInstance(declaringClass, -1 /* trusted */)
.unreflectSpecial(method, declaringClass)
.bindTo(object)
.invokeWithArguments(args);
}
}
static class Android extends Platform {
@Override public Executor defaultCallbackExecutor() {
return new MainThreadExecutor();
}
@Override CallAdapter.Factory defaultCallAdapterFactory(Executor callbackExecutor) {
return new ExecutorCallAdapterFactory(callbackExecutor);
}
static class MainThreadExecutor implements Executor {
private final Handler handler = new Handler(Looper.getMainLooper());
@Override public void execute(Runnable r) {
handler.post(r);
}
}
}
static class IOS extends Platform {
@Override public Executor defaultCallbackExecutor() {
return new MainThreadExecutor();
}
@Override CallAdapter.Factory defaultCallAdapterFactory(Executor callbackExecutor) {
return new ExecutorCallAdapterFactory(callbackExecutor);
}
static class MainThreadExecutor implements Executor {
private static Object queue;
private static Method addOperation;
static {
try {
// queue = NSOperationQueue.getMainQueue();
Class<?> operationQueue = Class.forName("org.robovm.apple.foundation.NSOperationQueue");
queue = operationQueue.getDeclaredMethod("getMainQueue").invoke(null);
addOperation = operationQueue.getDeclaredMethod("addOperation", Runnable.class);
} catch (Exception e) {
throw new AssertionError(e);
}
}
@Override public void execute(Runnable r) {
try {
// queue.addOperation(r);
addOperation.invoke(queue, r);
} catch (IllegalArgumentException | IllegalAccessException e) {
throw new AssertionError(e);
} catch (InvocationTargetException e) {
Throwable cause = e.getCause();
if (cause instanceof RuntimeException) {
throw (RuntimeException) cause;
} else if (cause instanceof Error) {
throw (Error) cause;
}
throw new RuntimeException(cause);
}
}
}
}
}
我们可以看到,如果检测到Android平台,有一个创建默认ExecutorCallAdapterFactory的方法(会在retrofit的build方法中调用,然后加到adapterFactories中),一个创建默认MainThreadExecutor的方法,它会获取ui线程的looper生成一个对应的handler,执行execute方法就是用主线程的handler执行handler.post(runnable)事件。Retrofit 需要 Java7 版本或 Android2.3 以上。
在build方法中我们可以看到必须传入baseurl,当不指定client的时候为默认的okhttpclient,callbackexecutor是回调执行者,call对象在子线程中获得网络数据之后转换到ui线程中,addCallAdapterFactory主要是对网络请求返回的call转换为observable 对象,addConverterFactory主要是对网络请求数据进行转化。最后通过建造者模式生成retrofit对象 把定义的接口转化为实例
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, 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);
}
});
}
可以看出我们采用动态代理的方式,返回了我们传入的接口的代理实例,并和InvocationHandler关联起来,当我们调用代理类的方法时,invoke方法都会被执行,
invoke方法中首先把method转化为servicemethod
ServiceMethod loadServiceMethod(Method method) {
ServiceMethod result;
synchronized (serviceMethodCache) {
result = serviceMethodCache.get(method);
if (result == null) {
result = new ServiceMethod.Builder(this, method).build();
serviceMethodCache.put(method, result);
}
}
return result;
}
通过建造者模式将method构建为ServiceMethod,
public Builder(Retrofit retrofit, Method method) {
this.retrofit = retrofit;
this.method = method;
this.methodAnnotations = method.getAnnotations();
this.parameterTypes = method.getGenericParameterTypes();
this.parameterAnnotationsArray = method.getParameterAnnotations();
}
public ServiceMethod build() {
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?");
}
responseConverter = createResponseConverter();
for (Annotation annotation : methodAnnotations) {
parseMethodAnnotation(annotation);
}
if (httpMethod == null) {
throw methodError("HTTP method annotation is required (e.g., @GET, @POST, etc.).");
}
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).");
}
}
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);
}
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.");
}
return new ServiceMethod<>(this);
}
在build方法中,构建calladapter对象,
private CallAdapter<?> createCallAdapter() {
Type returnType = method.getGenericReturnType();
if (Utils.hasUnresolvableType(returnType)) {
throw methodError(
"Method return type must not include a type variable or wildcard: %s", returnType);
}
if (returnType == void.class) {
throw methodError("Service methods cannot return void.");
}
Annotation[] annotations = method.getAnnotations();
try {
return retrofit.callAdapter(returnType, annotations);
} catch (RuntimeException e) { // Wide exception range because factories are user code.
throw methodError(e, "Unable to create call adapter for %s", returnType);
}
}
通过得到method的类型和注解,调用retrofit.callAdapter(returnType, annotations)——nextCallAdapter方法中会通过for循环从adapterFactories中获取calladAdapter对象,这会得到一个ExecutorCallAdapter对象;同理我们类似的得到responseConverter对象,主要是对数据进行转化。除此之外还会对方法注解进行解析
private void parseMethodAnnotation(Annotation annotation) {
if (annotation instanceof DELETE) {
parseHttpMethodAndPath("DELETE", ((DELETE) annotation).value(), false);
} else if (annotation instanceof GET) {
parseHttpMethodAndPath("GET", ((GET) annotation).value(), false);
} else if (annotation instanceof HEAD) {
parseHttpMethodAndPath("HEAD", ((HEAD) annotation).value(), false);
if (!Void.class.equals(responseType)) {
throw methodError("HEAD method must use Void as response type.");
}
} else if (annotation instanceof PATCH) {
parseHttpMethodAndPath("PATCH", ((PATCH) annotation).value(), true);
} else if (annotation instanceof POST) {
parseHttpMethodAndPath("POST", ((POST) annotation).value(), true);
} else if (annotation instanceof PUT) {
parseHttpMethodAndPath("PUT", ((PUT) annotation).value(), true);
} else if (annotation instanceof OPTIONS) {
parseHttpMethodAndPath("OPTIONS", ((OPTIONS) annotation).value(), false);
} else if (annotation instanceof HTTP) {
HTTP http = (HTTP) annotation;
parseHttpMethodAndPath(http.method(), http.path(), http.hasBody());
} else if (annotation instanceof retrofit2.http.Headers) {
String[] headersToParse = ((retrofit2.http.Headers) annotation).value();
if (headersToParse.length == 0) {
throw methodError("@Headers annotation is empty.");
}
headers = parseHeaders(headersToParse);
} else if (annotation instanceof Multipart) {
if (isFormEncoded) {
throw methodError("Only one encoding annotation is allowed.");
}
isMultipart = true;
} else if (annotation instanceof FormUrlEncoded) {
if (isMultipart) {
throw methodError("Only one encoding annotation is allowed.");
}
isFormEncoded = true;
}
}
以及参数注解进行解析等。
得到ServiceMethod对象后,我们通过接口传入的参数来得到okhttpcall对象
OkHttpCall(ServiceMethod<T> serviceMethod, Object[] args) {
this.serviceMethod = serviceMethod;
this.args = args;
}
然后就是把okhttpcall封装为call对象serviceMethod.callAdapter.adapt(okHttpCall)
calladpter就是之前提到的ExecutorCallAdapterFactory,在它的get方法中
public CallAdapter<Call<?>> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
if (getRawType(returnType) != Call.class) {
return null;
}
final Type responseType = Utils.getCallResponseType(returnType);
return new CallAdapter<Call<?>>() {
@Override public Type responseType() {
return responseType;
}
@Override public <R> Call<R> adapt(Call<R> call) {
return new ExecutorCallbackCall<>(callbackExecutor, call);
}
};
}
adapt方法会返回一个ExecutorCallBackCall对象,callbackExecutor就是我们在检测platform时创建的public Executor defaultCallbackExecutor() {
return new MainThreadExecutor();
},call是我们刚过传入的okhttpcall。
综上就是动态代理发挥了它的作用,你看上去是调用了接口的 方法,其实此时Retrofit把 接口翻译成一个HTTP请求,这个请求中有callAdapter,responseAdapter,okhttpcall三个重要的对象。我们得到接口的代理实例后,调用请求会触发InvocationHandler的invoke方法,并返回一个ExecutorCallBackcall对象,并把okhttpcall传入它的参数中,通过这个call对象完成我们的请求。有两种请求方式,execute和enqueue;
异步请求enqueue中
static final class ExecutorCallbackCall<T> implements Call<T> {
final Executor callbackExecutor;
final Call<T> delegate;
ExecutorCallbackCall(Executor callbackExecutor, Call<T> delegate) {
this.callbackExecutor = callbackExecutor;
this.delegate = delegate;
}
@Override public void enqueue(final Callback<T> callback) {
if (callback == null) throw new NullPointerException("callback == null");
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(ExecutorCallbackCall.this, new IOException("Canceled"));
} else {
callback.onResponse(ExecutorCallbackCall.this, response);
}
}
});
}
这里有两个对象,一个是callbackexecutor,一个是delegate,前者把网络线程切换到主线程中(我们在retrofit的build方法中检测platform时执行的),后者执行真正的网络请求(就是我们之前传入的callback对象)
@Override public void enqueue(final Callback<T> callback) {
if (callback == null) throw new NullPointerException("callback == null");
okhttp3.Call call;
Throwable failure;
synchronized (this) {
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) {
failure = creationFailure = t;
}
}
}
if (failure != null) {
callback.onFailure(this, failure);
return;
}
if (canceled) {
call.cancel();
}
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.onResponse(OkHttpCall.this, response);
} catch (Throwable t) {
t.printStackTrace();
}
}
});
}
在okhttpcall的enque对象中我们直接调用的okhttp进行的网络异步操作;类似的okhttpcall也是应用okhttp进行的同步请求。
下面是retrofit与另一款常用的volley库的简单对比:
Volley:
1.缓存处理;Volley自己就提供了一套完整的缓存处理方案,默认使用文件存储到磁盘中
2.代码简单,可读性高。
3.同一个请求如果同时都在发送,那么实际上只会有一个请求真正发出去, 其它的请求会等待这个结果回来
4.请求发送的时候提供了优先级的概念,但是是只保证顺序出去,不保证顺序回来
5.支持不同的Http客户端实现,默认提供了HttpClient和HttpUrlConnection的实现,而Retrofit在2.0版本之后,锁死在OkHttp上了。
6.支持请求取消
Retrofit:
1.较好的可扩展性,Volley中每一个新建一个Request时都需要指定一个父类,告知序列化数据的方式,而Retrofit中只需要在配置时,指定各种转换器即可。CallAdapter的存在,可以使你随意代理调用的Call
2.OkHttpClient自带并发光环,而Volley中的工作线程是自己维护的,那么就有可能存在线程由于异常退出之后,没有下一个工作线程补充的风险(线程池可以弥补这个缺陷),这在Retrofit中不存在
3.支持请求取消
4.Retrofit没有对缓存提供任何额外支持,缓存不在我们的控制范围之内,而是完全通过OkHttp来管理