在阅读retrofit源码的过程中主要参考了该博客:http://www.2cto.com/kf/201405/305248.html
在前面的几篇文章中,Platform看完了,RestAdapter的成员初始化完成,就要看怎么通过RestAdapter.create生成我们定义的接口的实现类了
/**Create an implementation of the API defined by the specified {@code service}interface. */
@SuppressWarnings("unchecked")
public <T> T create(Class<T> service) {
Utils.validateServiceClass(service);
return (T)Proxy.newProxyInstance(service.getClassLoader(), new Class<?>[] { service },
new RestHandler(getMethodInfoCache(service)));
}
Map<Method, RestMethodInfo>getMethodInfoCache(Class<?> service) {
synchronized (serviceMethodInfoCache) {
Map<Method, RestMethodInfo>methodInfoCache = serviceMethodInfoCache.get(service);
if (methodInfoCache == null) {
methodInfoCache = new LinkedHashMap<Method,RestMethodInfo>();
serviceMethodInfoCache.put(service,methodInfoCache);
}
return methodInfoCache;
}
}
使用了动态代理,InvocationHandler是RestHandler,RestHandler有一个参数,是Method->RestMethodInfo的映射,初始化时这个映射是空的。重点就是这两个了:RestHandler,RestMethodInfo,
下面是RestHandler的invoke方法,我们知道通过动态代理调用方法的时候,会通过invoke方法来完成。下面看看代码
@SuppressWarnings("unchecked") //
@Override public Object invoke(Object proxy, Methodmethod, final Object[] args)
throws Throwable {
// If the method is a method from Object then defer tonormal invocation.
if (method.getDeclaringClass() == Object.class) {//标注1
return method.invoke(this, args);
}
// Load or create the details cache for the currentmethod.
final RestMethodInfo methodInfo =getMethodInfo(methodDetailsCache, method);//标注2
if (methodInfo.isSynchronous) {//标注3
try {
return invokeRequest(requestInterceptor,methodInfo, args);
} catch (RetrofitError error) {
Throwable newError =errorHandler.handleError(error);
if (newError == null) {
throw new IllegalStateException("Error handler returned null for wrapped exception.",
error);
}
throw newError;
}
}
if (httpExecutor == null || callbackExecutor == null) {//标注四
throw new IllegalStateException("Asynchronous invocation requires calling setExecutors.");
}
if (methodInfo.isObservable) { //标注5
if (rxSupport == null) {
if (Platform.HAS_RX_JAVA) {
rxSupport = new RxSupport(httpExecutor, errorHandler,requestInterceptor);
} else {
throw new IllegalStateException("Observable method found but no RxJava on classpath.");
}
}
return rxSupport.createRequestObservable(new RxSupport.Invoker() {
@Override public ResponseWrapper invoke(RequestInterceptor requestInterceptor) {
return (ResponseWrapper)invokeRequest(requestInterceptor, methodInfo, args);
}
});
}
// Apply the interceptor synchronously, recording theinterception so we can replay it later.
// This way we still defer argument serialization to thebackground thread.
final RequestInterceptorTape interceptorTape = new RequestInterceptorTape();
requestInterceptor.intercept(interceptorTape);//标记6
Callback<?> callback =(Callback<?>) args[args.length - 1];//标记7
httpExecutor.execute(new CallbackRunnable(callback, callbackExecutor,errorHandler) {
@Override public ResponseWrapper obtainResponse() {
return (ResponseWrapper)invokeRequest(interceptorTape, methodInfo, args);
}
});
return null; //Asynchronous methods should have return type of void.
}
标注1:如果调用的是Object的方法,不做处理直接调用。
标注2:
static RestMethodInfogetMethodInfo(Map<Method, RestMethodInfo> cache, Method method) {
synchronized (cache) {
RestMethodInfo methodInfo =cache.get(method);
if (methodInfo == null) {
methodInfo = new RestMethodInfo(method);
cache.put(method, methodInfo);
}
return methodInfo;
}
}
获取method对应的RestMethodInfo,如果没有cache的,则从新建立,并缓存起来。
标注3:如果是同步调用(接口中直接返回数据,不通过Callback或Observe),直接调用invokeRequest,至于怎么样设置判断异步还是同步方式,请参见附录1.
标注4:检查是否具有callback等,如果没有,则给出错误。
标注5:如果是Observeble请求。(暂时不理解)
标记6:如果是非同步调用,先通过RequestInterceptorTape记录拦截请求,记录后在后台线程做实际拦截,后面会提到。
标记7:如果是Callback形式,交由线程池执行
1.请求是异步的还是同步的判别机制。
关键在于RestMethodInfo类,在invoke方法中,我们可以看到,method会被转换为RestMethodInfo并进行缓存。下面看看RestMethodInfo的构造方法。
RestMethodInfo(Method method) {
this.method = method;
responseType = parseResponseType();
isSynchronous = (responseType ==ResponseType.OBJECT);
isObservable = (responseType ==ResponseType.OBSERVABLE)
}
在invoke中的代码中可以看出,isSynchronous如果为true则表示是同步的,如果isObservable为true,则表示是异步的。而在上面的判断中有个很简单的判断,ResponseType为RestMethodInfo的一个内部枚举类型。
private enum ResponseType {
VOID,
OBSERVABLE,
OBJECT
}
那么关键点就在于,新建RestMethodInfo对象的时候,parseResponseType()方法了。
/** Loads{@link #responseObjectType}. Returns {@code true} if methodis synchronous. */
private ResponseType parseResponseType(){
// Synchronous methods have a non-void return type.
// Observable methods have a return type of Observable.
Type returnType = method.getGenericReturnType();
// Asynchronous methods should have a Callback type asthe last argument.
Type lastArgType = null;
Class<?> lastArgClass = null;
Type[] parameterTypes = method.getGenericParameterTypes();
if (parameterTypes.length > 0) {
Type typeToCheck =parameterTypes[parameterTypes.length - 1];
lastArgType = typeToCheck;
if (typeToCheck instanceof ParameterizedType) {
typeToCheck = ((ParameterizedType)typeToCheck).getRawType();
}
if (typeToCheck instanceof Class) {
lastArgClass = (Class<?>)typeToCheck;
}
}
boolean hasReturnType = returnType != void.class;
boolean hasCallback = lastArgClass != null && Callback.class.isAssignableFrom(lastArgClass);
// Check for invalid configurations.
if (hasReturnType && hasCallback) {
throw methodError("Must have return type or Callback aslast argument, not both.");
}
if (!hasReturnType && !hasCallback) {
throw methodError("Must have either a return type orCallback as last argument.");
}
if (hasReturnType) {
if (Platform.HAS_RX_JAVA) {
Class rawReturnType = Types.getRawType(returnType);
if (RxSupport.isObservable(rawReturnType)){
returnType = RxSupport.getObservableType(returnType,rawReturnType);
responseObjectType = getParameterUpperBound((ParameterizedType)returnType);
return ResponseType.OBSERVABLE;
}
}
responseObjectType = returnType;
return ResponseType.OBJECT;
}
lastArgType = Types.getSupertype(lastArgType,Types.getRawType(lastArgType), Callback.class);
if (lastArgType instanceof ParameterizedType) {
responseObjectType = getParameterUpperBound((ParameterizedType)lastArgType);
return ResponseType.VOID;
}
throw methodError("Last parameter must be of typeCallback<X> or Callback<? super X>.");
}
private static TypegetParameterUpperBound(ParameterizedType type) {
Type[] types = type.getActualTypeArguments();
for (int i = 0; i < types.length; i++) {
Type paramType = types[i];
if (paramType instanceof WildcardType) {
types[i] = ((WildcardType)paramType).getUpperBounds()[0];
}
}
return types[0];
}
通过上面可以看出,是通过method的最后一个参数的方法来判断的,并且可以获得一个规则,就是我们再定义接口方法的时候,返回值和callback参数必须有一个,不能同时存在,也不能都没有。
可以看出如果没有返回参数,并且platform具有rxjava,则为同步,否则为异步,如果最后一个参数是泛型参数,则类型为VOID
下一篇文章中,我们将介绍具体的请求执行。