Retrofit1.9源码解析(二)

Retrofit已经出到2.0了,但项目里的是1.9所以就来分析下它的源码。
要讲Retrofit,就必须要知道动态代理模式建造者模式。一开始使用的时,须要设置参数,如果没有设置,就用默认的。
restAdapter = new RestAdapter.Builder()
        .setEndpoint(
"" )
        .setLogLevel(RestAdapter.LogLevel.
FULL )
        .setClient(
new OkClient(getClient()))
        .setLog(
new RestAdapter.Log() {
           
@Override
           
public void log (String msg) {
                Log.
i(
TAG , msg) ;
           
}
        })
        .build();
private void ensureSaneDefaults () {
 
if ( converter == null ) {
   
converter = Platform.get().defaultConverter() ;
 
}
 
if ( clientProvider == null ) {
   
clientProvider = Platform.get().defaultClient() ;
 
}
 
if ( httpExecutor == null ) {
   
httpExecutor = Platform.get().defaultHttpExecutor() ;
 
}
 
if ( callbackExecutor == null ) {
   
callbackExecutor = Platform.get().defaultCallbackExecutor() ;
 
}
 
if ( errorHandler == null ) {
   
errorHandler = ErrorHandler. DEFAULT ;
 
}
 
if ( log == null ) {
   
log = Platform.get().defaultLog() ;
 
}
 
if ( requestInterceptor == null ) {
   
requestInterceptor = RequestInterceptor. NONE ;
 
}
}
设置好参数之后,就只需要通过以下代码就能得到clazz接口的代理,这里必须是接口。以前对代理模式以为只有在有实现者时才能使用,而Retrofit告诉我不只如此,虽然没有实现类,但通过代理已经实现了每个方法,具体做什么,是由框架自己决定的。
restAdapter .create(clazz) ;
从下面代码可以看出,重点是RestHandler.
public < T > T create (Class< T > service) {
  Utils.
validateServiceClass(service)
;
  return
( T ) Proxy. newProxyInstance(service.getClassLoader() , new Class<?>[] { service } ,
      new
RestHandler(getMethodInfoCache(service))) ;
}
首先是获取这个接口的缓存,如果已经解析过,就直接get,否则就新建个map,有个重点类RestMethodInfo。在RestMethodInfo里会判断两种情况,一种是返回值,一种是Callback回调,在这里只能使用一种。
/** Loads {@link #responseObjectType}. Returns {@code true} if method is 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 as the 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 as last argument, not both." ) ;
 
}
 
if (!hasReturnType && !hasCallback) {
   
throw methodError( "Must have either a return type or Callback 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 type Callback<X> or Callback<? super X>." ) ;
}
暂时只关注CallBack方式,的只需要CallBackRunnable那段代码就行。

private class RestHandler implements InvocationHandler {
 
private final Map<Method , RestMethodInfo> methodDetailsCache ;

 
RestHandler(Map<Method , RestMethodInfo> methodDetailsCache) {
   
this . methodDetailsCache = methodDetailsCache ;
 
}

 
@SuppressWarnings ( "unchecked" ) //
 
@Override public Object invoke (Object proxy , Method method , final 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) ;
   
}

   
// Load or create the details cache for the current method.
   
final RestMethodInfo methodInfo = getMethodInfo( methodDetailsCache , method) ;

    if
(methodInfo. isSynchronous ) {
     
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 ) {
     
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 the interception so we can replay it later.
    // This way we still defer argument serialization to the background thread.
   
final RequestInterceptorTape interceptorTape = new RequestInterceptorTape() ;
   
requestInterceptor .intercept(interceptorTape) ;

   
Callback<?> callback = (Callback<?>) args[args. length - 1 ] ;
   
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.
  }
下面这个是CallBackRunnable的Run代码,注意到一开始就调用了obtainResponse(),也是在这里发送请求的,又交给了RestAdapter类执行。
@SuppressWarnings ( "unchecked" )
@Override public final void run () {
 
try {
   
final ResponseWrapper wrapper = obtainResponse() ;
   
callbackExecutor .execute( new Runnable() {
     
@Override public void run () {
       
callback .success(( T ) wrapper . responseBody , wrapper . response ) ;
     
}
    })
;
 
} catch (RetrofitError e) {
    Throwable cause =
errorHandler .handleError(e) ;
    final
RetrofitError handled = cause == e ? e : unexpectedError(e.getUrl() , cause) ;
   
callbackExecutor .execute( new Runnable() {
     
@Override public void run () {
       
callback .failure( handled ) ;
     
}
    })
;
 
}
}
在下面代码里,一开始就去解析这个方法的Annotation跟参数Annotation,得到这个url的请求方式,路径,头部等信息。再经过RequestBuider跟ServerUrl组装起来,最后交给Client请求,在这里目前是OKClient.这个是在PlatForm里得到的。最后就把返回结果转化后回调CallBack,这个是通过Retrofit的线程池来的:

callbackExecutor .execute( new Runnable() {
 
@Override public void run () {
   
callback .success(( T ) wrapper . responseBody , wrapper . response ) ;
 
}
});

  /**
   * Execute an HTTP request.
   *
   *
@return HTTP response object of specified {@code type} or {@code null}.
   *
@throws RetrofitError if any error occurs during the HTTP request.
   */
 
private Object invokeRequest (RequestInterceptor requestInterceptor , RestMethodInfo methodInfo ,
     
Object[] args) {
    String url =
null;
    try
{
      methodInfo.init()
; // Ensure all relevant method information has been loaded.

     
String serverUrl = server .getUrl() ;
     
RequestBuilder requestBuilder = new RequestBuilder(serverUrl , methodInfo , converter ) ;
     
requestBuilder.setArguments(args) ;

     
requestInterceptor.intercept(requestBuilder) ;

     
Request request = requestBuilder.build() ;
     
url = request.getUrl() ;

      if
(!methodInfo. isSynchronous ) {
       
// If we are executing asynchronously then update the current thread with a useful name.
       
int substrEnd = url.indexOf( "?" , serverUrl.length()) ;
        if
(substrEnd == - 1 ) {
          substrEnd = url.length()
;
       
}
        Thread.
currentThread ().setName(
THREAD_PREFIX
           
+ url.substring(serverUrl.length() , substrEnd)) ;
     
}

     
if ( logLevel .log()) {
       
// Log the request data.
       
request = logAndReplaceRequest( "HTTP" , request , args) ;
     
}

      Object profilerObject =
null;
      if
( profiler != null ) {
        profilerObject =
profiler .beforeCall() ;
     
}

     
long start = System.nanoTime() ;
     
Response response = clientProvider .get().execute(request) ;
      long
elapsedTime = TimeUnit. NANOSECONDS .toMillis(System.nanoTime() - start) ;

      int
statusCode = response.getStatus() ;
      if
( profiler != null ) {
        RequestInformation requestInfo =
getRequestInfo(serverUrl
, methodInfo , request) ;
       
//noinspection unchecked
       
profiler .afterCall(requestInfo , elapsedTime , statusCode , profilerObject) ;
     
}

     
if ( logLevel .log()) {
       
// Log the response data.
       
response = logAndReplaceResponse(url , response , elapsedTime) ;
     
}

      Type type = methodInfo.
responseObjectType ;

      if
(statusCode >= 200 && statusCode < 300 ) { // 2XX == successful request
        // Caller requested the raw Response object directly.
       
if (type.equals(Response. class )) {
         
if (!methodInfo. isStreaming ) {
           
// Read the entire stream and replace with one backed by a byte[].
           
response = Utils. readBodyToBytesIfNecessary(response) ;
         
}

         
if (methodInfo. isSynchronous ) {
           
return response ;
         
}
         
return new ResponseWrapper(response , response) ;
       
}

        TypedInput body = response.getBody()
;
        if
(body == null ) {
         
if (methodInfo. isSynchronous ) {
           
return null;
         
}
         
return new ResponseWrapper(response , null ) ;
       
}

        ExceptionCatchingTypedInput wrapped =
new ExceptionCatchingTypedInput(body) ;
        try
{
          Object convert =
converter .fromBody(wrapped , type) ;
         
logResponseBody(body , convert) ;
          if
(methodInfo. isSynchronous ) {
           
return convert ;
         
}
         
return new ResponseWrapper(response , convert) ;
       
} catch (ConversionException e) {
         
// If the underlying input stream threw an exception, propagate that rather than
          // indicating that it was a conversion exception.
         
if (wrapped.threwException()) {
           
throw wrapped.getThrownException() ;
         
}

         
// The response body was partially read by the converter. Replace it with null.
         
response = Utils. replaceResponseBody(response , null ) ;

          throw
RetrofitError. conversionError(url , response , converter , type , e) ;
       
}
      }

      response = Utils.
readBodyToBytesIfNecessary (response)
;
      throw
RetrofitError. httpError(url , response , converter , type) ;
   
} catch (RetrofitError e) {
     
throw e ; // Pass through our own errors.
   
} catch (IOException e) {
     
if ( logLevel .log()) {
        logException(e
, url) ;
     
}
     
throw RetrofitError.networkError(url , e) ;
   
} catch (Throwable t) {
     
if ( logLevel .log()) {
        logException(t
, url) ;
     
}
     
throw RetrofitError.unexpectedError(url , t) ;
   
} finally {
     
if (!methodInfo. isSynchronous ) {
        Thread.
currentThread ().setName(
IDLE_THREAD_NAME ) ;
     
}
    }
  }
}

你可能感兴趣的:(Retrofit1.9源码解析(二))