手记

Android Retrofit实现原理分析

retrofit有几个关键的地方.

1.用户自定义的接口和接口方法.(由动态代理创建对象.)

2.converter转换器.(把response转换为一个具体的对象)

3.注解的使用.

让我们跟随Api来看吧.

RestAdapter restAdapter = new RestAdapter.Builder().setEndpoint(API_URL).build();

build()其内部实现是这样的:

[代码]java代码:

?

1

2

3

4

5

6

7

8

public RestAdapter build() {

     if (endpoint == null) {

       throw new IllegalArgumentException("Endpoint may not be null.");

     }

     ensureSaneDefaults();

     return new RestAdapter(endpoint, clientProvider, httpExecutor, callbackExecutor,

         requestInterceptor,   converter, profiler, errorHandler, log, logLevel);

   }

 

当用户没有设置自定义的converter,client, httpExecutor(http访问执行的线程–>只对异步的retrofit有效.), callBackExecutor(异步的callBack执行的线程), errorHandler, log, RequestInterceptor的时候,就会使用retrofit默认的配置.调用 ensureSaneDefaults();

[代码]java代码:

?

01

02

03

04

05

06

07

08

09

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

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;

    }

  }

}

 

可以看到进行初始化的时候调用了Platform.get()。

[代码]java代码:

?

01

02

03

04

05

06

07

08

09

10

11

12

13

14

15

16

17

private static final Platform PLATFORM = findPlatform();

static Platform get() {

  return PLATFORM;

}

private static Platform   findPlatform() {

  try {

    Class.forName("android.os.Build");//只要android.os.Build的class可以正常找到,证明是在android平台

    if (Build.VERSION.SDK_INT != 0) {

      return new Android();

    }

  } catch (ClassNotFoundException ignored) {

  }

  if (System.getProperty("com.google.appengine.runtime.version")   != null) {

    return new AppEngine();   //google的app Engine平台

  }

  return new Base();

} 

 

使用了单例的PLATFORM,通过findPlatform()初始化实例, 由于retrofit支持不同的平台,Platform用于判断使用的是哪个平台,如果是Android平台就使用Platform.Android,retrofit的Android类继承了Platform, 根据android的特性对配置项做了处理.如果是Google AppEngine就使用Platform.AppEngine,否则使用Platform.Base,这些都是Platform的子类,其中AppEngine又是Base的子类。 Platform是一个抽象类,定义了以下几个抽象方法,这几个方法的作用就是返回一些RestAdapter中需要要用到成员的默认实现

[代码]java代码:

?

01

02

03

04

05

06

07

08

09

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

private static class Android extends Platform {

   @Override Converter defaultConverter() {

     return new GsonConverter(new Gson());  //默认的转换器是Gson

   }

   @Override Client.Provider defaultClient() {

     final Client client;

     if (hasOkHttpOnClasspath()) {  //有okhttp的路径就使用 Okhttp

       client   = OkClientInstantiator.instantiate();

     } else if (Build.VERSION.SDK_INT < Build.VERSION_CODES.GINGERBREAD) {

       client   = new AndroidApacheClient();   //没有okhttp,且版本小于2.3 使用HttpClient

     } else {

       client   = new UrlConnectionClient();    //没有okhttp,且版本大于等于2.3 使用urlConnection.

     }

     return new Client.Provider() {

       @Override public Client get() {

         return client;

       }

     };

   }

   @Override Executor defaultHttpExecutor()   {   //网络访问执行的线程.

     return Executors.newCachedThreadPool(new ThreadFactory() {  //一个cached的线程池.可以复用老线程且线程长时间不用会自动回收. 线程池中线程不够会生成新线程.

       @Override public Thread newThread(final Runnable r) {

         return new Thread(new Runnable() {

           @Override public void run()   {

             Process.setThreadPriority(THREAD_PRIORITY_BACKGROUND);      //设置线程的优先级 为最低

             r.run();

           }

         },   RestAdapter.IDLE_THREAD_NAME);

       }

     });

   }

   @Override Executor defaultCallbackExecutor() { //异步执行的线程.

     return new MainThreadExecutor();

   }

   @Override RestAdapter.Log defaultLog() {  //通过Log.d("Retrofit",String)打印log

     return new AndroidLog("Retrofit");

   }

 }

 

其中判断了是否有okHttp的路径

[代码]java代码:

?

1

2

3

4

5

6

7

8

   private static boolean hasOkHttpOnClasspath()   {

  try {

    Class.forName("com.squareup.okhttp.OkHttpClient");   //是否可以找到OkHttpClient类.

    return true;

  } catch (ClassNotFoundException ignored) {

  }

  return false;

}

 

可以发现上面默认的Http的Executor是一个线程池.

而CallBack的Executor是在主线程执行的. 由绑定MainLooper的Handler提交到主线程执行.

[代码]java代码:

?

1

2

3

4

5

6

    public final class MainThreadExecutor   implements Executor   {

  private final Handler handler = new Handler(Looper.getMainLooper()); //关联主线程的Handler

  @Override public void execute(Runnable   r) {

    handler.post(r);                                   //提交到主线程执行

  }

}

 

[代码]java代码:

?

1

2

3

4

public final boolean post(Runnable r)

    {

       return  sendMessageDelayed(getPostMessage(r), 0);

    }

 

[代码]java代码:

?

1

2

3

4

5

private static Message   getPostMessage(Runnable r) {   //把runnable封装到Message中.

    Message m =   Message.obtain();

    m.callback = r;

    return m;

}

 

现在有下面一个接口,

[代码]java代码:

?

1

2

3

4

  interface SimplePOST{

    @POST("/android")  

    Response   getResponse();

} 

 

下面了解下 SimplePOST simplePost= adapter.create(SimplePOST.class)的内部逻辑.

[代码]java代码:

?

1

2

3

4

5

public <t> T create(Class<t> service) {

    Utils.validateServiceClass(service);                                                       

    return (T)   Proxy.newProxyInstance(service.getClassLoader(), new Class<!--?-->[] { service   },   //动态代理

        new RestHandler(getMethodInfoCache(service)));

  }</t></t>

 

[代码]java代码:

?

1

2

3

4

5

6

7

8

static <t> void validateServiceClass(Class<t> service)   {      //确保create()参数是一个接口类型,且这个接口没有继承其他的接口.(使用动态代理的前提)

  if (!service.isInterface()) {

    throw new IllegalArgumentException("Only interface endpoint definitions   are supported.");

  }

  if (service.getInterfaces().length > 0) {

    throw new IllegalArgumentException("Interface definitions must not extend   other interfaces.");

  }

}</t></t>

 

可以发现adapter.create()方法的内部实现是利用动态代理生成了service接口的一个实现类. 根据动态代理的原理. 可以得知调用实现类的方法其实就是调用InvocationtHandler的对应方法.     虽然这里是运用了动态代理的技术.但是却和一般的动态代理不一样. 一般的动态代理的InvocationHandler应该通过构造函数中传入委托类A.然后在invoke方法中调用A的方法, 但这里是没有委托类的.只是利用动态代理自动生成接口的实现类.

  因为java的动态代理是基于接口的,所以retrofit也要求用户自定义的也必须是一个接口.

  注意invocationHandler的invoke()方法执行是在我们调用接口的方法的时候执行的.对于上面的代码就simplepost.getResponse()执行的时候.

所以上面的代码先对传入的Class 进行校验:Utils.validateServiceClass(service),必须是接口,并且不能是一个没有自己函数并继承自其他父接口的空接口。 校验完成后返回一个动态代理类,我们想要知道retrofit使用用户自定义的接口干了什么事,就需要查看new RestHandler(getMethodInfoCache(service)) 的具体实现。

RestHandler 继承自 InvocationHandler 实现它的 invoke 函数,当代理类的接口函数被调用时,会先调用代理类的invoke 函数,然后在invoke 函数里通过反射调用用户指定的接口函数。

查看invoke 函数的具体实现之间,我们先分析分析getMethodInfoCache(service)函数。

下面是getMethodInfoCache函数的实现部分

[代码]java代码:

?

01

02

03

04

05

06

07

08

09

10

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;

    }

  }</method,></method,></method,>

 

该函数使用了同步代码块 synchronized 以serviceMethodInfoCache为对象锁,防止其他线程在该函数执行的时候入侵,之后在serviceMethodInfoCache查询service是否在其中存在,如果不存在,就新new 一个LinkedHashMap<Method, RestMethodInfo>加入其中,RestMethodInfo是一个final 类型的class,下面是它的申明

[代码]java代码:

?

01

02

03

04

05

06

07

08

09

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

/** Request metadata about a service   interface declaration. */

final class RestMethodInfo   {

final Method method;

  boolean loaded = false;   //方法是否已经load过(解析过)

  // Method-level details

  final ResponseType responseType;

  final boolean isSynchronous;      //方法是同步还是异步.

  final boolean isObservable;

  Type responseObjectType;

  RequestType requestType =   RequestType.SIMPLE;

  String requestMethod;

  boolean requestHasBody;

  String   requestUrl;          

  Set<string>   requestUrlParamNames;

  String requestQuery;

  List<retrofit.client.header>   headers;

  String contentTypeHeader;

  boolean isStreaming;

  private enum ResponseType {  //方法的返回值是什么类型

    VOID,                        //void代表没有返回值,-->异步的方式

    OBSERVABLE,                 //rxjava

    OBJECT                      //方法的返回值是对象--->同步的方式

  }

  RestMethodInfo(Method method)   {

    this.method =   method;

    responseType =   parseResponseType();

    isSynchronous =   (responseType == ResponseType.OBJECT);

    isObservable =   (responseType ==             ResponseType.OBSERVABLE);

  }

   private ResponseType parseResponseType() {

    // Synchronous   methods have a non-void return type.       //同步的方法有一个非void的返回值

    // Observable   methods have a return type of Observable.   //Observable的方法 返回值类型应该是Observable

    Type returnType =   method.getGenericReturnType();

    // Asynchronous   methods should have a Callback type as the last argument. //异步的方法最后一个方法的参数类型应该是Callback.

    Type lastArgType   = nul

    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);   //如果有CallBack,   CallBack只能是最后一个参数.

    // Check for   invalid configurations.

    if (hasReturnType && hasCallback)   {                           //返回值是非void类型和方法有CallBack参数有且只能有一个满足.

      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-->.");

  }

private void parsePath(String   path) {          //解析路径 如GET(string),注意这里会对string进行判断,必须以"/"开头. 所以不能是空字符串,如""

    ...........

}

  List<retrofit.client.header>   parseHeaders(String[] headers) {  //解析Headers注解.

  .....

}

  private void parseParameters() {   //解析方法参数,如方法参数的@Header, @Query等.

  .......

}

  private void parseMethodAnnotations() { //解析http方式.如GET(),POST()

  .......

 }

}</retrofit.client.header></x></retrofit.client.header></string>

 

从RestMethodInfo类的注释来看,它和用户自定义的接口有密切的关系,也就是说,用户接口中定义的函数,由该类来解析说明和发出请求。

之后就将methodDetailsCache(LinkedHashMap<Method, RestMethodInfo>类型)传入到RestHandler类的构造方法当中,为其的同名属性完成赋值的同时返回该类的实例。接下来我们就开始分析RestHandler中的invoke 函数,这可以说是retrofit的精髓所在。

[代码]java代码:

?

001

002

003

004

005

006

007

008

009

010

011

012

013

014

015

016

017

018

019

020

021

022

023

024

025

026

027

028

029

030

031

032

033

034

035

036

037

038

039

040

041

042

043

044

045

046

047

048

049

050

051

052

053

054

055

056

057

058

059

060

061

062

063

064

065

066

067

068

069

070

071

072

073

074

075

076

077

078

079

080

081

082

083

084

085

086

087

088

089

090

091

092

093

094

095

096

097

098

099

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

private class RestHandler   implements InvocationHandler   {

  private final Map<method, restmethodinfo=""> methodDetailsCache;

  RestHandler(Map<method,   restmethodinfo=""> methodDetailsCache) {  //一般的动态代理.InvocationHandler构造函数一般要传入委托类.

    this.methodDetailsCache   = methodDetailsCache;

  }

  @SuppressWarnings("unchecked")   //

  @Override public Object invoke(Object proxy, Method method, final Object[] args)  //动态代理的方法实现.调用委托类的方法,最终会调用invoke方法.

      throws Throwable {

    // If the method   is a method from Object then defer to normal invocation.

    if (method.getDeclaringClass() == Object.class)   {  //因为接口默认也继承Object.所以接口也有Object中的方法的. 如继承自Object如equals()方法

      return method.invoke(this, args);  //这里需要注意下,这里调用的是invocationHandler(H)的方法.一般的动态代理这里应该是调用委托类(A)的方法.

    }

    // Load or create   the details cache for the current method.

    final RestMethodInfo methodInfo =   getMethodInfo(methodDetailsCache, method);  //把method和RestMethodInfo缓存起来.防止重复解析method.(把方法的注解,返回值,同步异步等信息都解析出来储存在RestMethodInfo中.)

    if (methodInfo.isSynchronous) {  //同步的方式.

      try {

        return invokeRequest(requestInterceptor,   methodInfo, args);  //核心方法(网络访问).   //可以看到retrofit的synchronous类型方法并不是子线程执行的. 所以在Android平台使用同步方式的retrofit的话要在子线程中.

      } catch (RetrofitError error) {

        Throwable   newError = errorHandler.handleError(error);

        if (newError == null) {

          throw new IllegalStateException("Error handler returned null for wrapped   exception.",  //自定义的ErrorHandler的hanleError()方法不能return null.

              error);

        }

        throw newError;  //注意,同步的方式,当遇到错误的时候,会抛出一个RuntimeException.在Android下尽量不要使用同步的方式(因为RuntimeException是不提示用户主动捕捉的).

      }

    }

    if (httpExecutor == null || callbackExecutor == null) {

      throw new IllegalStateException("Asynchronous invocation requires calling   setExecutors.");

    }

    if (methodInfo.isObservable) {   //rx的方式

      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);

        }

      });

    }

    //同步, Observable方式都不是的话,肯定是异步的方式了.

    // 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) {  //可以看到在Android上异步方式是通过HttpExecutor执行的.是默认子线程执行的. 所以异步方式的retrofit不需要在子线程中执行.

      @Override public ResponseWrapper obtainResponse() {

        return (ResponseWrapper)   invokeRequest(interceptorTape, methodInfo, args);

      }

    });

    return null; // Asynchronous methods should have   return type of void.

  }

  /**

   * 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.  --->保证method的参数,返回值,注解都解析完成. 可以得到网络访问的url,header,query,访问方式等信息.

      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);  //调用okHttp或者其他Client进行网络访问.并把返回的数据封装进retrofit的Response中.

      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   //返回码在200到300之间认为是一次成功的网络访问.

        //   Caller requested the raw Response object directly.

        if (type.equals(Response.class))   {                         //如果方法的返回值类型(封装在responseObjectType)是retrofit的Response的话. 那就不用converter转换.

          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)   {                     //① 结合下面的②   ,返回值类型不同是因为invokeRequest()分别由2个不同的方法调用.  ①是由 invoke()调用的.

            return null;

          }

          return new ResponseWrapper(response, null);       //②   的情况是异步的. 是由callBack模式中的obtainResponse()中调用的.  下面和上面的返回值类型不同的情况皆是如此

        }

        ExceptionCatchingTypedInput   wrapped = new ExceptionCatchingTypedInput(body);

        try {

          Object   convert = converter.fromBody(wrapped, type); //方法的返回值是非Response. 那么由Converter把Response转换成对应的类型.

          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);

      }

    }

  }

}</method,></method,>

 

下面来分析每一步的调用流程。 (一)判断call的method是不是属于当前代理Object申明的,如果是就返回方法调用后的结果而不继续向下执行。

(二)调用getMethodInfo函数 传入参数为调用RestHandler构造方法时传入的methodDetailsCache(LinkedHashMap<Method, RestMethodInfo>类型)和具体调用的method(Method类型),返回值是一个RestMethodInfo的实例。getMethodInfo函数主要作用是将用户调用的method解析为一个RestMethodInfo实例,然后再将method和该RestMethodInfo实例以key-value键值对的形式绑定,存放在methodDetailsCache中,然后再将该RestMethodInfo实例返回。(ps: RestMethodInfo中的对Mehod接口解析是很重要的,但是这里作者就一笔带过了,读者自己看看吧,就是JAVA反射那套东西,还是很简单的)

(三)调用并返回invokeRequest函数 这里拿到了将method解析后的methodInfo(RestMethodInfo类型),判断该调用函数用户是想让它同步执行还是异步执行(利用RestMethodInfo中的isSynchronous属性判断),同步执行则进入到if判断,调用并返回invokeRequest函数.

第一个参数RequestInterceptor接口是一个请求拦截器,能在请求执行之前向请求添加一些额外的数据,在最开始分析RestAdapter 创建的时候分析到ensureSaneDefaults 函数,如果没有在创建RestAdapter的时候传入自己实现的RequestInterceptor,那么Retrofit会给一个默认的RequestInterceptor空实现,指向RequestInterceptor接口类中的NONE属性。第二个参数是刚才Method解析后的RestMethodInfo,第三个参数是用户调用函数时传入的参数数组。

methodInfo.init() 这个函数调用之后会将当前用户调用的方法进行进一步的解析,比如对@POST @GET @HEAD…etc 这些annotation的解析,并且每个实例只解析一次。 RequestBuilder requestBuilder = new RequestBuilder(serverUrl, methodInfo, converter); 从字面字面意思看,这个类和请求有关。确实,这个类里包含了用户请求网络所包含的各种参数,比如Host地址,Http协议头…etc 反正就是组成一个http请求所必要的东西。 Request request = requestBuilder.build(); 由requestBuilder调用build函数产生一个Request类,该类是一个常量实体类,包含了最少的请求Http时所需要的信息。之后是请求信息的日志打印,在接下来关键的地方来了。

[代码]java代码:

?

1

2

3

long start = System.nanoTime();

Response response =   clientProvider.get().execute(request);

 long elapsedTime =   TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - start);

 

start 表示请求开始的时间,elapsedTime 表示该次请求花费的时间,而中间那句则是进行真正的网络请求,clientProvider 表示你在前面创建RestAdapter 时调调用ensureSaneDefaults函数所初始化的网络请求客户端(可能是OkClient, AndroidApacheClient,UrlFetchClient或者UrlConnectionClient四个的其中之一)。执行完成后返回一个response 这是一个Response常量实体类,和前面提到的Request常量实体类对应(一个表示请求实体,一个表示相应实体),里面存放着该次请求返回的Http协议头,状态码,body…etc .

在请求之前还有一个profiler

[代码]java代码:

?

1

2

3

4

Object profilerObject = null;

       if (profiler != null) {

         profilerObject   = profiler.beforeCall();

       }

 

这里用到了AOP(面向切面)设计模式,如果用户设置了profiler的话,在请求的前后分别会调用profiler的beforeCall和afterCall函数,以通知用户请求的完成情况(在afterCall函数中传递了响应结果)。 之后的代码就是对response 的一个处理了,如果响应结果不在200到300之间,Retrofit会抛出一个自定义的异常进行进一步的处理,如果在200到300之间则会对response的请求数据做进一步的处理 .比如调用new ResponseWrapper(response, convert);利用converter(Converter接口类型,但实际上是GsonConverter,对Gson的一个封装) 将数据解析为用户想要返回的那个类型。

如果判断用户不是希望同步执行,那么invokeRequest函数的执行将会在之后执行。首先,会判断你是否使用了RxJava。如果使用了RxJava ,则组建一个RxSupport(对RxJava 中类的简单封装),使用它的createRequestObservable函数对invokeRequest函数进行异步调用并返回一个ResponseWrapper。否则使用httpExecutor(前面初始化的时候被设置为CachedThreadPool(缓存线程池))对invokeRequest函数进行异步调用并返回一个ResponseWrapper。

最后看看CallbackRunnable的实现

[代码]java代码:

?

01

02

03

04

05

06

07

08

09

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

abstract class CallbackRunnable<t>   implements Runnable   {

  private final Callback<t> callback;

  private final Executor callbackExecutor;

  private final ErrorHandler errorHandler;

  CallbackRunnable(Callback<t>   callback, Executor callbackExecutor, ErrorHandler errorHandler) {

    this.callback =   callback;

    this.callbackExecutor   = callbackExecutor;

    this.errorHandler   = errorHandler;

  }

  @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);

        }

      });

    }

  }

  public abstract ResponseWrapper obtainResponse();

} </t></t></t>

 

就是一个普通的Runnable,在run方法中首先执行obtailResponse,从名字可以看到是执行请求返回Response,这个从前面可以看到执行了invokeRequest,和同步调用中一样执行请求。 紧接着就提交了一个Runnable至callbackExecutor,在看Platform时看到了callbackExecotor是通过Platform.get().defaultCallbackExecutor()返回的,Android中是向主线程的一个Handler发消息

值得注意的事,对于同步调用,如果遇到错误是直接抛异常,而对于异步调用,是调用Callback.failure()

retrofit的大体流程

 用户自定义配置项的设置(如client,converter,拦截器等)—>解析接口的方法(如果曾经解析过就从缓存中获取),确定http访问的url,header,method等,确定是异步还是同步的方式——>使用具体的Client进行网络访问,并将数据封装到Response—->执行Converter的逻辑(有可能不用执行),把Response数据转换为一个具体对象.—>根据同步或者异步的方式,执行方法或者callBack的逻辑.   ### retrofit框架的需要注意的几个小点.

1.为什么同步方式不像正常的方式一样要求用户try_catch来提醒用户捕捉异常?

  通过上面的逻辑可以看到,真正进行网络访问,converter转换的逻辑都在invokeHandler.invoke()方法执行的时候执行. 而这个方法的调用是在 用户自定义接口调用接口方法的时候执行的.(不明白的可以看下动态代理的原理).而用户自定义的接口方法是没有抛出异常的.在java中,如果父类方法没有抛出异常,子类方法也不能显示的抛出异常.(子类方法只能抛出父类方法抛出异常或其子类).所以Retrofit就不能抛出各种异常(如IO异常). 并且要抓住异常后转换为RuntimeException抛出.(动态代理生成的接口的实现类其实内部也采用了同样的方法.)

  异常抓住后不能直接内部处理,应该提醒用户代码执行的时候出了问题,所以必须抓住异常后再次抛出.而对于CallBack的方式,因为有failure()方法提示用户代码逻辑出了问题,所以就不用re-throw异常了.

  2.关于 InvocationHandler的invoke()方法, 这个方法有个返回值. 那这个返回值返回的是什么呢?

  首先明确Method.invoke(Object receiver,Object.. args)是和 receiver.method(args)等价的,2个方法的返回值是一样的.

public Object invoke(Object receiver, Object… args) 这里的Object是方法执行的的返回值. —> Returns the result of dynamically invoking this method. Equivalent to {@code receiver.methodName(arg1, arg2, … , argN)}.   动态代理生成了接口A的代理类B,B的同名方法内部其实调用的是invocationHandler的 invoke()方法.返回的也是invoke方法的返回值. 所以invoke返回的类型就应该和接口方法的返回值类型一样.

原文链接:http://www.apkbus.com/blog-705730-61179.html

0人推荐
随时随地看视频
慕课网APP