從源碼角度深入理解Retrofit2

Retrofit2作爲目前最火的網絡請求框架之一,它是一個由Square
組織開發的可以在Android和java中使用的安全型HTTP客戶端(官方文檔描述“Type-safe HTTP client for Android and Java by Square”)。本文將從Retrofit2簡單使用入手,在對其源碼進行分析來深入理解Retrofit2(基於2.5.0版本)

  • 1.Retrofit2簡單使用

    • 1.1 下面,根據官方例子,簡單使用一個get請求來演示Retrofit2簡單使用。首先gradle中添加retrofit依賴,創建一個描述每一個請求的接口

       /**
        * gradle中添加依賴 
        */
       implementation 'com.squareup.retrofit2:retrofit:2.5.0'
      
      public interface GitHub {
      
      public static final String API_URL = "https://api.github.com";
      //使用Get 請求
      @GET("/repos/{owner}/{repo}/contributors")
      Call<List<SimpleService.Contributor>> contributors(
              @Path("owner") String owner,
              @Path("repo") String repo);
      }
      
    • 1.2 創建網絡請求數據bean對象

      public class SimpleService {
      public static class Contributor {
          public final String login;
          public final int contributions;
      
          public Contributor(String login, int contributions) {
              this.login = login;
              this.contributions = contributions;
          }
        }
      }
      
    • 1.3 創建retrofit對象,傳入網絡請求的域名地址,傳入剛剛創建的請求對象接口,而我們的網絡請求默認返回JSON數據,而retrofit請求默認返回response.body()(異步請求),所以我們需要添加一個GsonConverterFactory轉換器將JSON轉化爲我們的bean對象,需要在gradle中添加如下庫的依賴

      /**
       * gradle中添加依賴 
       */
      implementation 'com.squareup.retrofit2:converter-gson:2.5.0'
      
       // Create a very simple REST adapter which points the GitHub API.
         Retrofit retrofit=new Retrofit.Builder()
                 .baseUrl(GitHub.API_URL)
                 .addConverterFactory(GsonConverterFactory.create())
                 .build();
         // Create an instance of our GitHub API interface.
         GitHub gitHub = retrofit.create(GitHub.class);
         // Create a call instance for looking up Retrofit contributors.
         final retrofit2.Call<List<SimpleService.Contributor>> call = gitHub.contributors("square", "retrofit");
      
    • 1.4 根據上一步拿到的call對象執行同步網絡請求獲取數據,耗時操作開啓子線程執行

       new Thread(){
            @Override
            public void run() {
                super.run();
                /**
                 * 同步請求
                try {
                    List<SimpleService.Contributor> contributors = call.execute().body();
                    for (SimpleService.Contributor contributor : contributors) {
                     Log.e("maoqitian","Retrofit同步請求返回參數"+contributor.login + " (" + contributor.contributions + ")");
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }.start();
      
      
    • 1.5 根據上一步拿到的call對象執行異步網絡請求獲取數據

      call.enqueue(new retrofit2.Callback<List<SimpleService.Contributor>>() {
            @Override
            public void onResponse(retrofit2.Call<List<SimpleService.Contributor>> call, retrofit2.Response<List<SimpleService.Contributor>> response) {
                List<SimpleService.Contributor> body = response.body();
                for (SimpleService.Contributor contributor : body) {
                    Log.e("maoqitian","Retrofit異步請求返回參數"+contributor.login + " (" + contributor.contributions + ")");
                }
            }
      
            @Override
            public void onFailure(retrofit2.Call<List<SimpleService.Contributor>> call, Throwable t) {
                Log.e("maoqitian","Retrofit異步請求失敗"+t.getMessage());
            }
        });
      
  • 2.源碼分析

    • 2.1 retrofit2網絡請求基本流程圖

    • 根據上面的簡單使用retrofit的例子,我們可以概括一下大致流程圖


    • 2.2 retrofit對象創建

    • 我們先了解retrofit對象包含了哪些成員變量以及他們的含義和作用

      //ServiceMethod 的緩存,從接口中解析出來,放在這個 map 裏面。
      private final Map<Method, ServiceMethod<?>> serviceMethodCache = new ConcurrentHashMap<>();
      //okhttp3.Call.Factory接口對象,接口聲明瞭newCall方法
      final okhttp3.Call.Factory callFactory;
      //OKHttp3 的HttpUrl 對象,描述了一個 http 地址 
      final HttpUrl baseUrl;
      //保存ConverterFactory轉換器的list,通過Retrofit.Builder的 addConverterFactory方法來添加
      final List<Converter.Factory> converterFactories;
      //保存CallAdapterFactory適配器的list,通過Retrofit.Builder的 addCallAdapterFactory方法來添加
      final List<CallAdapter.Factory> callAdapterFactories;
      //回調函數的執行器,也就是回調函數執行的線程,Android 中默認爲 MainThreadExecutor
      final @Nullable Executor callbackExecutor;
      //創建動態代理對象之前,是否提前解析接口 Method,創建 ServiceMethod 並添加到 Cache 中。
      final boolean validateEagerly;
      
    • 接着就是創建Retrofit對象new Retrofit.Builder(),一看到Builder我們就可以想到構造者模式,通過外部對各個參數的配置來儘可能的達到各種業務請求場景的要求。先看看Builder()中的操作

      /** Retrofit的 Builder方法*/
      public Builder() {
        this(Platform.get());
      }
      /**Platform類中的get方法*/
      static Platform get() {
      return PLATFORM;
      }
      
      private static final Platform PLATFORM = findPlatform();
      /**Platform類中的findPlatform方法*/
      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) {
      }
      return new Platform();
      }
      /**Platform類中的Android方法*/
      static class Android extends Platform {
      @IgnoreJRERequirement // Guarded by API check.
      @Override boolean isDefaultMethod(Method method) {
        if (Build.VERSION.SDK_INT < 24) {
          return false;
        }
        return method.isDefault();
      }
      
      @Override public Executor defaultCallbackExecutor() {
        return new MainThreadExecutor();
      }
      
      @Override List<? extends CallAdapter.Factory> defaultCallAdapterFactories(
          @Nullable Executor callbackExecutor) {
        if (callbackExecutor == null) throw new AssertionError();
        ExecutorCallAdapterFactory executorFactory = new ExecutorCallAdapterFactory(callbackExecutor);
        return Build.VERSION.SDK_INT >= 24
          ? asList(CompletableFutureCallAdapterFactory.INSTANCE, executorFactory)
          : singletonList(executorFactory);
      }
      
      @Override int defaultCallAdapterFactoriesSize() {
        return Build.VERSION.SDK_INT >= 24 ? 2 : 1;
      }
      
      @Override List<? extends Converter.Factory> defaultConverterFactories() {
        return Build.VERSION.SDK_INT >= 24
            ? singletonList(OptionalConverterFactory.INSTANCE)
            : Collections.<Converter.Factory>emptyList();
      }
      
      @Override int defaultConverterFactoriesSize() {
        return Build.VERSION.SDK_INT >= 24 ? 1 : 0;
      }
      
      static class MainThreadExecutor implements Executor {
        private final Handler handler = new Handler(Looper.getMainLooper());
      
        @Override public void execute(Runnable r) {
          handler.post(r);
        }
       }
      }
      
    • 由上述源碼可以看到,Retrofit的builder方法中調用了Platform.get()方法,最終調用的是findPlatform(),該方法使用反射判斷當前的環境來得到不同的Platform對象,接着回到Retrofit的build方法

     /** Retrofit的 build方法*/
     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> callAdapterFactories = new ArrayList<>(this.callAdapterFactories);
      callAdapterFactories.addAll(platform.defaultCallAdapterFactories(callbackExecutor));
    
       // Make a defensive copy of the converters.
       List<Converter.Factory> converterFactories = new ArrayList<>(
          1 + this.converterFactories.size() + platform.defaultConverterFactoriesSize());
    
        // 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());
       converterFactories.addAll(this.converterFactories);
       converterFactories.addAll(platform.defaultConverterFactories());
    
       return new Retrofit(callFactory, baseUrl, unmodifiableList(converterFactories),
          unmodifiableList(callAdapterFactories), callbackExecutor, validateEagerly);
       }
     }
    
    • 可以看到build方法中callFactory就是OkHttpClient對象,也就是Retrofit的網絡請求也是通過OKHttp來完成的;在Android環境中,build中platform調用的方法都是前面提到的Platform的繼承類Android中實現的方法,callbackExecutor在主線程執行,默認加載的CallAdapter.Factory爲ExecutorCallAdapterFactory,如果Build.VERSION.SDK_INT >= 24(Android 7.0),則Converter.Factory默認爲OptionalConverterFactory,否則爲空。最終新建retrofit對象並將設置和默認的參數傳入。

    • 2.3 retrofit.create(class)

    • 創建了retrofit對象之後,接着調用了retrofit的create方法,先看看該方法的實現

      /**Retrofit類的create方法*/
      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();
            private final Object[] emptyArgs = new Object[0];
      
            @Override public Object invoke(Object proxy, Method method, @Nullable 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);
              }
              return loadServiceMethod(method).invoke(args != null ? args : emptyArgs);
            }
          });
       }
      
    • 看到retrofit的create方法,代碼很少,看到關鍵代碼Proxy,我們就可以知道這裏使用了Java的動態代理,爲了方便下面代碼的解讀,我們先來簡單瞭解什麼是動態代理。

    • 代理模式

    • 代理是一種常用的設計模式,其目的就是爲其他對象提供一個代理以控制對某個對象的訪問。代理類負責爲委託類預處理消息,過濾消息並轉發消息,以及進行消息被委託類執行後的後續處理。而代理分爲動態代理和靜態代理,靜態代理中每一個需要被代理的類都要創建一個代理類,這顯然很麻煩,所以Java給我們提供了java.lang.reflect.InvocationHandler接口和 java.lang.reflect.Proxy 的類來支持動態代理

      //Object proxy:被代理的對象  
      //Method method:要調用的方法  
      //Object[] args:方法調用時所需要參數  
      public interface InvocationHandler {  
      public Object invoke(Object proxy, Method method, Object[] args) throws Throwable;  
      } 
      
      //CLassLoader loader:類的加載器  
      //Class<?> interfaces:得到全部的接口  
      //InvocationHandler h:得到InvocationHandler接口的子類的實例  
      public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) throws IllegalArgumentException  
      
    • 更詳細動態代理知識可以自行了解

    • 現在我們回過頭看retrofit的create方法,Proxy.newProxyInstance方法加載了我們的網絡請求描述接口類和其中定義的方法,並實現了InvocationHandler接口,也就是說create方法實現了動態代理,則調用create方法,也就會調用InvocationHandler接口實現的invoke方法。

    • 在InvocationHandler接口實現的invoke方法中,如果是 Object對象本身方法(比如equals、toString、hashCode等)以及 Platform 默認的方法(java8默認方法,1.8的新特性),則在正常使用的時候調用返回,如果不滿足,最後調用 loadServiceMethod(method)方法,也就是該方法來解析對應接口中我們定義的描述網絡請求的方法。

    • 2.4 解析描述網絡請求接口

    • 上一小節我們說到loadServiceMethod(method)方法解析對應接口

       /**Retrofit類的loadServiceMethod方法 */
       ServiceMethod<?> loadServiceMethod(Method method) {
        ServiceMethod<?> result = serviceMethodCache.get(method);
        if (result != null) return result;
      
        synchronized (serviceMethodCache) {
        result = serviceMethodCache.get(method);
        if (result == null) {
          result = ServiceMethod.parseAnnotations(this, method);
          serviceMethodCache.put(method, result);
         }
        }
       return result;
       }
      
    • 通過該方法,解析接口之後返回的對象是ServiceMethod,如果之前解析過,則直接從serviceMethodCache取出直接返回,否則調用ServiceMethod.parseAnnotations方法進行解析

       /**ServiceMethod<T> 抽象類的parseAnnotations方法**/
       static <T> ServiceMethod<T> parseAnnotations(Retrofit retrofit, Method method) {
       RequestFactory requestFactory = RequestFactory.parseAnnotations(retrofit, method);
      
        Type returnType = method.getGenericReturnType();
        if (Utils.hasUnresolvableType(returnType)) {
        throw methodError(method,
            "Method return type must not include a type variable or wildcard: %s", returnType);
        }
        if (returnType == void.class) {
        throw methodError(method, "Service methods cannot return void.");
       }
      
        return HttpServiceMethod.parseAnnotations(retrofit, method, requestFactory);
       }
      
    • 如上源碼,RequestFactory負責解析接口並且生成Request,繼續看RequestFactory的 parseAnnotations方法

       /**RequestFactory 類的parseAnnotations方法**/
       static RequestFactory parseAnnotations(Retrofit retrofit, Method method) {
       return new Builder(retrofit, method).build();
       }
       /**RequestFactory 類的build方法**/
       RequestFactory build() {
        for (Annotation annotation : methodAnnotations) {
        //解析網絡請求方法註解
          parseMethodAnnotation(annotation);
        }
        //省略部分代碼
        ......
        int parameterCount = parameterAnnotationsArray.length;
        parameterHandlers = new ParameterHandler<?>[parameterCount];
        for (int p = 0; p < parameterCount; p++) {
          //方法參數註解的解析
          parameterHandlers[p] = parseParameter(p, parameterTypes[p], parameterAnnotationsArray[p]);
        }
        //省略部分代碼
        .......
        return new RequestFactory(this);
      }
      /**RequestFactory 類的parseMethodAnnotation方法**/
      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);
          //剩餘其他請求方法註解解析
          ......
          isFormEncoded = true;
        }
      }
      /**RequestFactory 類的parseHttpMethodAndPath方法**/
      private void parseHttpMethodAndPath(String httpMethod, String value, boolean hasBody) {
        if (this.httpMethod != null) {
          throw methodError(method, "Only one HTTP method is allowed. Found: %s and %s.",
              this.httpMethod, httpMethod);
        }
        this.httpMethod = httpMethod;
        this.hasBody = hasBody;
      
        if (value.isEmpty()) {
          return;
        }
        // Get the relative URL path and existing query string, if present.
        int question = value.indexOf('?');
        if (question != -1 && question < value.length() - 1) {
          // Ensure the query string does not have any named parameters.
          String queryParams = value.substring(question + 1);
          Matcher queryParamMatcher = PARAM_URL_REGEX.matcher(queryParams);
          if (queryParamMatcher.find()) {
            throw methodError(method, "URL query string \"%s\" must not have replace block. "
                + "For dynamic query parameters use @Query.", queryParams);
          }
        }
        this.relativeUrl = value;
        this.relativeUrlParamNames = parsePathParameters(value);
      }
      /**RequestFactory 類的parsePathParameters方法**/
      static Set<String> parsePathParameters(String path) {
        Matcher m = PARAM_URL_REGEX.matcher(path);
        Set<String> patterns = new LinkedHashSet<>();
        while (m.find()) {
          patterns.add(m.group(1));
        }
        return patterns;
      }
      
    • 在解析網絡請求註解的方法parseMethodAnnotation中,通過instanceof判斷描述網絡請求接口的註解中是否包含對應網絡請求類型,如果包含則調用parseHttpMethodAndPath設置httpMethod網絡請求方法(get),聯繫到上面的簡單例子,相對url(對應/repos/{owner}/{repo}/contributors),hasBody在get請求中沒有,在post請求中爲post的參數體,relativeUrlParamNames(對應owner、repo)爲相對路徑中需要外部傳遞參數佔位符名稱,通過正則表達式獲取。

    • 上面我們的分析中只是解析了網絡請求註解,還需要解析接口方法參數的註解,看到RequestFactory的parseAnnotations方法中的parseParameter方法

       /**RequestFactory 類的parseParameter方法**/
       private ParameterHandler<?> parseParameter(
          int p, Type parameterType, @Nullable Annotation[] annotations) {
        ParameterHandler<?> result = null;
        if (annotations != null) {
          for (Annotation annotation : annotations) {
            ParameterHandler<?> annotationAction =
                parseParameterAnnotation(p, parameterType, annotations, annotation);
                //省略部分代碼
                ....
            }    
         }
        return result;
       }
        /**RequestFactory 類的parseParameterAnnotation方法**/
       @Nullable
       private ParameterHandler<?> parseParameterAnnotation(
          int p, Type type, Annotation[] annotations, Annotation annotation) {
          //省略部分代碼
        .......     
        else if (annotation instanceof Path) {
          validateResolvableType(p, type);
          //各種檢查判斷
          .....
          gotPath = true;
      
          Path path = (Path) annotation;
          String name = path.value();
          validatePathName(p, name);
      
          Converter<?, String> converter = retrofit.stringConverter(type, annotations);
          return new ParameterHandler.Path<>(name, converter, path.encoded());
        }
        //省略代碼
        ......
        }
        /**ParameterHandler 類的Path實現**/
        static final class Path<T> extends ParameterHandler<T> {
        //省略代碼
        ......
        @Override void apply(RequestBuilder builder, @Nullable T value) throws IOException {
        if (value == null) {
          throw new IllegalArgumentException(
              "Path parameter \"" + name + "\" value must not be null.");
        }
        builder.addPathParam(name, valueConverter.convert(value), encoded);
        }
       }
       /**RequestBuilder 類的addPathParam方法**/
       void addPathParam(String name, String value, boolean encoded) {
        if (relativeUrl == null) {
        // The relative URL is cleared when the first query parameter is set.
        throw new AssertionError();
        }
       String replacement = canonicalizeForPath(value, encoded);
       String newRelativeUrl = relativeUrl.replace("{" + name + "}", replacement);
       if (PATH_TRAVERSAL.matcher(newRelativeUrl).matches()) {
        throw new IllegalArgumentException(
            "@Path parameters shouldn't perform path traversal ('.' or '..'): " + value);
        }
        relativeUrl = newRelativeUrl;
       }
      
    • 由上源碼(源碼較多,截取Path註解處理原理),RequestFactory 類的parseParameter方法通過遍歷參數註解,調用parseParameterAnnotation方法獲取了註解中定義的參數值(path.value()),最後返回了new ParameterHandler.Path<>對象,在ParameterHandler類的Path實現中調用RequestBuilder類(創建請求)的addPathParam方法最終將相對路徑relativeUrl的佔位符通過描述網絡請求接口方法傳遞的參數替換掉得到正確的相對路徑relativeUrl。而得到正確相對路徑的RequestBuilder對象創建則在RequestFactory類的create方法中。

    • 2.5 調用接口中的方法返回Call對象

    • 現在我們再次回到ServiceMethod的parseAnnotations方法,經過上面2.4小節的分析我們已經得到了解析到正確相對路徑的RequestFactory對象,最終該方法調用了HttpServiceMethod.parseAnnotations()

       /**
        * Inspects the annotations on an interface method to construct a reusable service method that
        * speaks HTTP. This requires potentially-expensive reflection so it is best to build each service
        * method only once and reuse it.
        * HttpServiceMethod的parseAnnotations方法
        */
        static <ResponseT, ReturnT> HttpServiceMethod<ResponseT, ReturnT> parseAnnotations(
        Retrofit retrofit, Method method, RequestFactory requestFactory) {
        //最終通過retrofit對象拿到默認CallAdapter.Factory對象(ExecutorCallAdapterFactory)
        CallAdapter<ResponseT, ReturnT> callAdapter = createCallAdapter(retrofit, method);
        Type responseType = callAdapter.responseType();
        if (responseType == Response.class || responseType == okhttp3.Response.class) {
        throw methodError(method, "'"
            + Utils.getRawType(responseType).getName()
            + "' is not a valid response body type. Did you mean ResponseBody?");
         }
         if (requestFactory.httpMethod.equals("HEAD") && !Void.class.equals(responseType)) {
         throw methodError(method, "HEAD method must use Void as response type.");
         }
         //最終通過retrofit拿到設置的Converter.Factory對象(我們設置了GsonConverterFactory)
         Converter<ResponseBody, ResponseT> responseConverter =
          createResponseConverter(retrofit, method, responseType);
      
         okhttp3.Call.Factory callFactory = retrofit.callFactory;
         return new HttpServiceMethod<>(requestFactory, callFactory, callAdapter, responseConverter);
       }
       
      
    • 通過該方法源碼,首先我們可以知道最剛開始我們分析retrofit的create方法中loadServiceMethod(method)方法實際上就是HttpServiceMethod對象,接着繼續看parseAnnotations方法中的createCallAdapter方法

      /**HttpServiceMethod 類的createCallAdapter方法**/
      private static <ResponseT, ReturnT> CallAdapter<ResponseT, ReturnT> createCallAdapter(
        Retrofit retrofit, Method method) {
      Type returnType = method.getGenericReturnType();
      Annotation[] annotations = method.getAnnotations();
       try {
        //noinspection unchecked
        return (CallAdapter<ResponseT, ReturnT>) retrofit.callAdapter(returnType, annotations);
        } catch (RuntimeException e) { // Wide exception range because factories are user code.
        throw methodError(method, e, "Unable to create call adapter for %s", returnType);
        }
      }
       /**Retrofit 類的callAdapter方法**/
       public CallAdapter<?, ?> callAdapter(Type returnType, Annotation[] annotations) {
       return nextCallAdapter(null, returnType, annotations);
       }
       /**Retrofit 類的nextCallAdapter方法**/
       public CallAdapter<?, ?> nextCallAdapter(@Nullable CallAdapter.Factory skipPast, Type returnType,
        Annotation[] annotations) {
      checkNotNull(returnType, "returnType == null");
      checkNotNull(annotations, "annotations == null");
      
      int start = callAdapterFactories.indexOf(skipPast) + 1;
      for (int i = start, count = callAdapterFactories.size(); i < count; i++) {
        CallAdapter<?, ?> adapter = callAdapterFactories.get(i).get(returnType, annotations, this);
        if (adapter != null) {
          return adapter;
        }
       }
       //省略部分代碼
        ......
      }
      
    • 由上源碼HttpServiceMethod通過自身createCallAdapter調用Retrofit 類的callAdapter方法,而Retrofit 類的callAdapter方法又調用 Retrofit 類的nextCallAdapter方法遍歷callAdapterFactories來得到CallAdapter.Factory對象;前面我們分析retrofit對象創建時已經說過Platform對象中提供了默認的CallAdapter.Factory對象爲ExecutorCallAdapterFactory,該對象也就是HttpServiceMethod的createCallAdapter方法得到的CallAdapter.Factory對象。同理,HttpServiceMethod的createResponseConverter最終通過retrofit的nextResponseBodyConverter方法得到了Converter(GsonRequestBodyConverter)對象(我們設置了GsonConverterFactory.responseBodyConverter的方法創建了該對象),這裏就不貼代碼了。

    • 接着上面的分析,我們在代理的invoke方法中返回了loadServiceMethod(method).invoke(args != null ? args : emptyArgs)這一句代碼,當retrofit.create生成的的接口對象調用其中的接口的方法,則會觸發動態代理執行invoke方法,最終返回loadServiceMethod(method).invoke,也就是執行了HttpServiceMethod.ivnoke方法

        /**HttpServiceMethod 類的invoke方法**/
       @Override ReturnT invoke(Object[] args) {
       return callAdapter.adapt(
          new OkHttpCall<>(requestFactory, args, callFactory, responseConverter));
       }
      
    • 可以看到HttpServiceMethod類的invoke方法中調用了callAdapter.adapt,而這個callAdapter經過我們前面的分析已經知道是默認添加的ExecutorCallAdapterFactory對象,繼續看ExecutorCallAdapterFactory對象

       /**ExecutorCallAdapterFactory 類**/
       final class ExecutorCallAdapterFactory extends CallAdapter.Factory {
       final Executor callbackExecutor;
      
       ExecutorCallAdapterFactory(Executor callbackExecutor) {
       this.callbackExecutor = callbackExecutor;
       }
      
        @Override public @Nullable CallAdapter<?, ?> get(
        Type returnType, Annotation[] annotations, Retrofit retrofit) {
        if (getRawType(returnType) != Call.class) {
        return null;
        }
        final Type responseType = Utils.getCallResponseType(returnType);
        return new CallAdapter<Object, Call<?>>() {
        @Override public Type responseType() {
          return responseType;
        }
      
        @Override public Call<Object> adapt(Call<Object> call) {
          return new ExecutorCallbackCall<>(callbackExecutor, call);
         }
        };
       }
       /**ExecutorCallbackCall 類**/
       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) {
        checkNotNull(callback, "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);
                }
              }
            });
          }
          @Override public void onFailure(Call<T> call, final Throwable t) {
            callbackExecutor.execute(new Runnable() {
              @Override public void run() {
                callback.onFailure(ExecutorCallbackCall.this, t);
              }
            });
          }
        });
        }
      //省略代碼
      ......
      @Override public Response<T> execute() throws IOException {
        return delegate.execute();
      }
       //省略代碼
      ......
      }
      
    • 通過ExecutorCallAdapterFactory的源碼應該會有一種讓你恍然大悟的感覺

      • 1.通過ExecutorCallAdapterFactory的adapt方法,我們我們已經得到了Call對象,它就是ExecutorCallbackCall
      • 2.ExecutorCallbackCall的enqueue方法執行在主線程,callbackExecutor就是Platfrom默認添加的MainThreadExecutor(Android環境中),所以callback.onResponse中隨意更新UI
      • 3.delegate對象就是OkHttpCall對象,所以我們Call執行的enqueue和execute方法都是OkHttpCall對象對象的enqueue和execute方法。
    • Retrofit中的適配器模式和裝飾模式

      • 適配器模式做爲兩個不同的接口之間的橋樑,使得Retrofit2.Call接口可以使用OKHttp.Call的實現來執行網絡請求,而適配器就是CallAdapter.Factory
      • 裝飾模式在不改變原有類的基礎上進行擴展,也就是ExecutorCallbackCall,對OKHttp.Call進行裝飾,本身它執行enqueue方法是在子線程中,而ExecutorCallbackCall對其裝飾讓其返回值執行在主線程中。
      • 下面通過一張圖來幫助理解


    • 2.6 Call對象執行網絡請求

    • 通過上一小節的分析,我們來看看OkHttpCall對象是如何執行網絡請求的

       /*OkHttpCall類的enqueue方法*/
       @Override public void enqueue(final Callback<T> callback) {
       checkNotNull(callback, "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) {
            throwIfFatal(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) {
          Response<T> response;
          try {
            response = parseResponse(rawResponse);
          } catch (Throwable e) {
            throwIfFatal(e);
            callFailure(e);
            return;
          }
      
          try {
            callback.onResponse(OkHttpCall.this, response);
          } catch (Throwable t) {
            t.printStackTrace();
          }
         }
      
        @Override public void onFailure(okhttp3.Call call, IOException e) {
          callFailure(e);
        }
      
        private void callFailure(Throwable e) {
          try {
            callback.onFailure(OkHttpCall.this, e);
          } catch (Throwable t) {
            t.printStackTrace();
          }
        }
        });
       }
      /*OkHttpCall類的execute方法*/
      @Override public Response<T> execute() throws IOException {
       okhttp3.Call call;
       synchronized (this) {
        if (executed) throw new IllegalStateException("Already executed.");
        executed = true;
        //省略部分代碼
        .......
        call = rawCall;
        if (call == null) {
          try {
            call = rawCall = createRawCall();
          } catch (IOException | RuntimeException | Error e) {
           //省略部分代碼
          .......
        }
        return parseResponse(call.execute());
       }
      
    • 通過以上源碼,我們可以看到執行完全請求的是okhttp3.Call對象,也就是說retrofit的網絡請求時由OKHttp3來完成的,繼續看得到okhttp3.Call對象的createRawCall()方法

       /*OkHttpCall類的createRawCall方法*/
       private okhttp3.Call createRawCall() throws IOException {
       okhttp3.Call call = callFactory.newCall(requestFactory.create(args));
       if (call == null) {
        throw new NullPointerException("Call.Factory returned null.");
       }
       return call;
       }
      /*retrofit類的build方法*/
       public Retrofit build() {
        okhttp3.Call.Factory callFactory = this.callFactory;
        //省略部分代碼
          .......
        if (callFactory == null) {
          callFactory = new OkHttpClient();
        }
        //省略部分代碼
          .......
       }
       
      
    • 通過OkHttpCall類的createRawCall方法和retrofit類的build方法,callFactory.newCall,也就是OkHttpClient.nawCall,而requestFactory.create()返回的就是OKHttp的 request 對象,經過前面的分析,RequestFactory解析好的請求數據傳遞給了OkHttpClient。

    • 關於OkHttpClient是如何執行網絡請求的可以看我之前的一篇文章

    • 2.7 Converter對象轉換網絡請求成功返回數據

    • 通過上一小節,我們已經通過OkHttp進行了實際的網絡請求,請求成功的數據根據之前新建Retrofit對象的時候我們指定了GsonConverterFactory,並在HttpServiceMethod通過createResponseConverter方法得到了GsonResponseBodyConverter對象(可以查看2.5小節分析)。

    • 請求成功返回的數據會經過OkHttpCall類的parseResponse方法進行處理

       /*OkHttpCall類的parseResponse方法*/
       Response<T> parseResponse(okhttp3.Response rawResponse) throws IOException {
       ResponseBody rawBody = rawResponse.body();
      
       // Remove the body's source (the only stateful object) so we can pass the response along.
       rawResponse = rawResponse.newBuilder()
          .body(new NoContentResponseBody(rawBody.contentType(), rawBody.contentLength()))
          .build();
      //省略部分代碼
          .......
       ExceptionCatchingResponseBody catchingBody = new ExceptionCatchingResponseBody(rawBody);
       try {
        T body = responseConverter.convert(catchingBody);
        return Response.success(body, rawResponse);
       } catch (RuntimeException e) {
         //省略部分代碼
          .......
       }
      }
      /* GsonResponseBodyConverter類*/
      final class GsonResponseBodyConverter<T> implements Converter<ResponseBody, T> {
      private final Gson gson;
      private final TypeAdapter<T> adapter;
      
      GsonResponseBodyConverter(Gson gson, TypeAdapter<T> adapter) {
      this.gson = gson;
      this.adapter = adapter;
       }
       @Override public T convert(ResponseBody value) throws IOException {
       JsonReader jsonReader = gson.newJsonReader(value.charStream());
       try {
        T result = adapter.read(jsonReader);
        if (jsonReader.peek() != JsonToken.END_DOCUMENT) {
          throw new JsonIOException("JSON document was not fully consumed.");
        }
        return result;
         } finally {
        value.close();
        }
       }
      }
      
    • 通過以上源碼可以看到通過Retrofit對象指定GsonConverterFactory後得到的GsonResponseBodyConverter的對象幫我們把Json數據通過Gson處理成我們指定的bean對象,很方便。到此,retrofit的源碼分析就結束了。

    • 最後通過一張類之間調用流程圖來幫助更好理解retrofit源碼


Retrofit整個框架源碼量其實不算太多,其中巧妙的運用設計模式來完成整個框架設計。靜下心來閱讀源碼對自己的提升還是很有幫助的。由於本人水平有限,文章中如果有錯誤,請大家給我提出來,大家一起學習進步,如果覺得我的文章給予你幫助,也請給我一個喜歡和關注。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章