從源碼角度深刻理解Retrofit2

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

  • 1.Retrofit2簡單使用

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

      /**
        * 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對象git

      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中添加以下庫的依賴github

      /**
       * 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對象執行異步網絡請求獲取數據json

      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的例子,咱們能夠歸納一下大體流程圖設計模式

      retrofit2網絡請求基本示意流程圖

    • 2.2 retrofit對象建立

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

      //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對其裝飾讓其返回值執行在主線程中。

      • 下面經過一張圖來幫助理解

        retrofit適配器模式和裝飾模式

    • 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網絡請求類流程圖(Android)

Retrofit整個框架源碼量其實不算太多,其中巧妙的運用設計模式來完成整個框架設計。靜下心來閱讀源碼對本身的提高仍是頗有幫助的。因爲本人水平有限,文章中若是有錯誤,請你們給我提出來,你們一塊兒學習進步,若是以爲個人文章給予你幫助,也請給我一個喜歡和關注。

相關文章
相關標籤/搜索