andorid网络框架retrofit源码解析三

在阅读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;

    }

  }

 

使用了动态代理,InvocationHandlerRestHandlerRestHandler有一个参数,是Method->RestMethodInfo的映射,初始化时这个映射是空的。重点就是这两个了:RestHandlerRestMethodInfo,

 

下面是RestHandlerinvoke方法,我们知道通过动态代理调用方法的时候,会通过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如果是同步调用(接口中直接返回数据,不通过CallbackObserve),直接调用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


下一篇文章中,我们将介绍具体的请求执行。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值