Retrofit的原理解析

前言

上篇文章我們分析了OkHttp的原理,不難看出它更多的還是和TCP/IP打交道,做了請(qǐng)求和響應(yīng)的處理,今天我們來介紹另外一位主人公,那就是我們的Retrofit,它更多的是對(duì)OkHttp做了一層封裝,方便了我們調(diào)用接口,并且對(duì)數(shù)據(jù)進(jìn)行了轉(zhuǎn)化,對(duì)業(yè)務(wù)側(cè)更加友好。
首先我們來看看它的初始化,慢慢剖析它的源碼吧。

        Retrofit retrofit = new Retrofit.Builder().baseUrl(BaseUrl.BASE_URL)
                .addConverterFactory(GsonConverterFactory.create())
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                .client(httpClient)
                .build();

老相識(shí)又出現(xiàn)了Builder,我們接著看

Retrofit.Builder()

    Builder(Platform platform) {
      this.platform = platform;
    }
    public Builder() {
      this(Platform.get());
    }

代碼很清楚,這里進(jìn)行了平臺(tái)的獲取并且賦值。

Builder.baseUrl

    public Builder baseUrl(String baseUrl) {
      Objects.requireNonNull(baseUrl, "baseUrl == null");
      return baseUrl(HttpUrl.get(baseUrl));
    }

    public Builder baseUrl(HttpUrl baseUrl) {
      Objects.requireNonNull(baseUrl, "baseUrl == null");
      List<String> pathSegments = baseUrl.pathSegments();
      if (!"".equals(pathSegments.get(pathSegments.size() - 1))) {
        throw new IllegalArgumentException("baseUrl must end in /: " + baseUrl);
      }
      this.baseUrl = baseUrl;
      return this;
    }

這里也是比較簡單就是對(duì)baseUrl進(jìn)行賦值,返回當(dāng)前的Builder對(duì)象。后面的幾個(gè)基本都一樣,感興趣的可以自己追一下。

Builder.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());
       //返回一個(gè) 創(chuàng)建的Retrofit對(duì)象
      return new Retrofit(callFactory, baseUrl, unmodifiableList(converterFactories),
          unmodifiableList(callAdapterFactories), callbackExecutor, validateEagerly);
    }

我們接著看看Retrofit的創(chuàng)建,如下:

  Retrofit(okhttp3.Call.Factory callFactory, HttpUrl baseUrl,
      List<Converter.Factory> converterFactories, List<CallAdapter.Factory> callAdapterFactories,
      @Nullable Executor callbackExecutor, boolean validateEagerly) {
    this.callFactory = callFactory;
    this.baseUrl = baseUrl;
    this.converterFactories = converterFactories; // Copy+unmodifiable at call site.
    this.callAdapterFactories = callAdapterFactories; // Copy+unmodifiable at call site.
    this.callbackExecutor = callbackExecutor;
    this.validateEagerly = validateEagerly;
  }

其實(shí)也是簡單的一些屬性的賦值。到這里我們簡單的Retrofit創(chuàng)建就完成了。下面分析大頭,接口的創(chuàng)建請(qǐng)求以及調(diào)用回調(diào)。’

public interface OKHttpService {
    /**
     * 登錄接口demo
     */
    @FormUrlEncoded
    @POST("user/login")
    Call<ResponseBody> login(@Field("username") String num, @Field("password") String password);

我這里簡單創(chuàng)建了個(gè)登錄接口。

        OKHttpService httpService = retrofit.create(OKHttpService.class);
        httpService.login("zc", "123123").enqueue(new Callback<ResponseBody>() {
            @Override
            public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
                Log.i("ZC", "成功: " + Thread.currentThread());
            }

            @Override
            public void onFailure(Call<ResponseBody> call, Throwable t) {
                Log.i("ZC", "失敗: " + Thread.currentThread());
            }
        });

接著我們通過create去創(chuàng)建并且發(fā)送請(qǐng)求,我們一步步的看下去:

create

  public <T> T create(final Class<T> service) {
    validateServiceInterface(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 @Nullable 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);
            }
            //loadServiceMethod創(chuàng)建的代理方法對(duì)象,其內(nèi)部包含了login方法的注解參數(shù),返回值,以及各個(gè)工廠以及各請(qǐng)求器轉(zhuǎn)換器等等的適配操作
            return loadServiceMethod(method).invoke(args != null ? args : emptyArgs);
          }
        });
  }

這里的invoke我們?cè)谙旅娣治觥?/p>

動(dòng)態(tài)代理模式:在程序運(yùn)行期間,通過反射機(jī)制,動(dòng)態(tài)創(chuàng)建OkhttpService.class的代理對(duì)象,并且對(duì)該對(duì)象中的方法增加一些其他操作

newProxyInstance

    @CallerSensitive
    public static Object newProxyInstance(ClassLoader loader,
                                          Class<?>[] interfaces,
                                          InvocationHandler h)
        throws IllegalArgumentException
    {
        Objects.requireNonNull(h);
        //若interface沒有重寫clone(),默認(rèn)的是進(jìn)行一次淺拷貝,即實(shí)例對(duì)象相同,引用不同
        final Class<?>[] intfs = interfaces.clone();
        // Android-removed: SecurityManager calls
        /*
        final SecurityManager sm = System.getSecurityManager();
        if (sm != null) {
            checkProxyAccess(Reflection.getCallerClass(), loader, intfs);
        }
        */

        /*
         * Look up or generate the designated proxy class.
          *生成或獲取(緩存中)代理類的Class對(duì)象
         */
        Class<?> cl = getProxyClass0(loader, intfs);

        /*
         * Invoke its constructor with the designated invocation handler.
         */
        try {
            // Android-removed: SecurityManager / permission checks.
            /*
            if (sm != null) {
                checkNewProxyPermission(Reflection.getCallerClass(), cl);
            }
            */
            //通過Class對(duì)象獲取構(gòu)造方法
            final Constructor<?> cons = cl.getConstructor(constructorParams);
            final InvocationHandler ih = h;
            if (!Modifier.isPublic(cl.getModifiers())) {
                // BEGIN Android-removed: Excluded AccessController.doPrivileged call.
                /*
                AccessController.doPrivileged(new PrivilegedAction<Void>() {
                    public Void run() {
                        cons.setAccessible(true);
                        return null;
                    }
                });
                */

                cons.setAccessible(true);
                // END Android-removed: Excluded AccessController.doPrivileged call.
            }
            //通過構(gòu)造方法創(chuàng)建實(shí)例對(duì)象
            return cons.newInstance(new Object[]{h});
        } catch (IllegalAccessException|InstantiationException e) {
            throw new InternalError(e.toString(), e);
        } catch (InvocationTargetException e) {
            Throwable t = e.getCause();
            if (t instanceof RuntimeException) {
                throw (RuntimeException) t;
            } else {
                throw new InternalError(t.toString(), t);
            }
        } catch (NoSuchMethodException e) {
            throw new InternalError(e.toString(), e);
        }
    }

getProxyClass0獲取的Class對(duì)象其實(shí)是個(gè)單例模式,在第一次時(shí)會(huì)創(chuàng)建實(shí)例并將其存入WeakCache做緩存,之后的獲取會(huì)直接從緩存中獲取Class對(duì)象,至于其他一些操作,多為反射機(jī)制實(shí)例化對(duì)象常用的調(diào)用。

還有一點(diǎn)我們需要記住的是,InvocationHandler內(nèi)部的invoke被調(diào)用是我們通過newProxyInstance()返回的代理類對(duì)象(OKHttpService的代理實(shí)現(xiàn)類)調(diào)用login()時(shí),觸發(fā)invoke()。

至此我們就簡單的分析完了Proxy.newProxyInstance()中的源碼,我們繼續(xù)回到create()源碼中,return代理對(duì)象,至此OKHttpService接口的代理對(duì)象就被創(chuàng)建了,接下來就要使用代理對(duì)象OKHttpService調(diào)用login()方法了。

調(diào)用login()時(shí)我們會(huì)調(diào)用InvocationHandler#invoke()。

ServiceMethod對(duì)象實(shí)例化
一個(gè)ServiceMethod對(duì)象對(duì)應(yīng)了一個(gè)網(wǎng)絡(luò)接口中的方法,該對(duì)象中保存有方法的處理網(wǎng)絡(luò)請(qǐng)求所要用到的各種參數(shù)及方法的屬性注解等,閱讀源碼時(shí)要搞清楚serviceMethod的性質(zhì),這里調(diào)用了loadServiceMethod()我們進(jìn)入方法內(nèi)部看看。

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

同樣,首先會(huì)從緩存中獲取對(duì)象,為null才會(huì)創(chuàng)建實(shí)例對(duì)象,也是一個(gè)單例對(duì)象,在Builer()中會(huì)將解析method一些信息(參數(shù),注解,參數(shù)注解)和retrofit對(duì)象中的屬性,并保存到serviceMethod對(duì)象中。
延伸知識(shí)點(diǎn)(繼續(xù)深追源碼):ServiceMethod不僅存儲(chǔ)了method(也就是login()方法)的參數(shù),屬性等,還存儲(chǔ)有各種適配器,轉(zhuǎn)換器,和http協(xié)議要求的一些相關(guān)check,需要結(jié)合http相關(guān)的知識(shí)來理解。這里直接給結(jié)論,就不繼續(xù)追了。

HttpServiceMethod#invoke

  @Override final @Nullable ReturnT invoke(Object[] args) {
    //創(chuàng)建一個(gè)網(wǎng)絡(luò)請(qǐng)求器,所以說Retrofit底層默認(rèn)是使用okhttp實(shí)現(xiàn)的
    Call<ResponseT> call = new OkHttpCall<>(requestFactory, args, callFactory, responseConverter);
     //將okhttpcall對(duì)象與網(wǎng)絡(luò)請(qǐng)求適配器進(jìn)行綁定
    return adapt(call, args);
  }

不難看出,它創(chuàng)建了個(gè)OkHttpCall對(duì)象,retrofit2#OkHttpCall重寫了execute()和enqueue方法等,在隨后的網(wǎng)絡(luò)請(qǐng)求適配器調(diào)用中,就會(huì)執(zhí)行此方法來通過OkHttp請(qǐng)求訪問網(wǎng)絡(luò)

adapt(call, args)

將創(chuàng)建的okHttpCall對(duì)象與serviceMethod中的網(wǎng)絡(luò)請(qǐng)求適配器適配,內(nèi)部return callAdapter.adapt(call);而此callAdapter還記得在哪獲取的?
它是在serviceMethod.loadServiceMethod(method)內(nèi)的createCallAdapter()中選擇的,所以這里的引用是之前選擇的網(wǎng)絡(luò)請(qǐng)求適配器類對(duì)象的adapt(),我們就先看一下它默認(rèn)的網(wǎng)絡(luò)請(qǐng)求適配器也就是DefaultCallAdapterFactory。

DefaultCallAdapterFactory #get#CallAdapter#adapt

  @Override public @Nullable CallAdapter<?, ?> get(
      Type returnType, Annotation[] annotations, Retrofit retrofit) {
    if (getRawType(returnType) != Call.class) {
      return null;
    }
    if (!(returnType instanceof ParameterizedType)) {
      throw new IllegalArgumentException(
          "Call return type must be parameterized as Call<Foo> or Call<? extends Foo>");
    }
    final Type responseType = Utils.getParameterUpperBound(0, (ParameterizedType) returnType);

    final Executor executor = Utils.isAnnotationPresent(annotations, SkipCallbackExecutor.class)
        ? null
        : callbackExecutor;

    return new CallAdapter<Object, Call<?>>() {
      @Override public Type responseType() {
        return responseType;
      }

      @Override public Call<Object> adapt(Call<Object> call) {
        return executor == null
            ? call
            : new ExecutorCallbackCall<>(executor, call);
      }
    };
  }

當(dāng)執(zhí)行了serviceMethod.adapt(okHttpCall)時(shí),其實(shí)(默認(rèn))調(diào)用了此處的adapt()方法,返回一個(gè)call對(duì)象。
小小整理一下:
當(dāng)客戶端調(diào)用login()方法時(shí),是使用的Proxy.newProxyInstance()返回的代理實(shí)例對(duì)象httpService去調(diào)用的,并且會(huì)回調(diào)InvocationHandler中的invoke()方法,執(zhí)行代理操作,最后通過adapt()返回一個(gè)call對(duì)象。

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

        public void enqueue(final Callback<T> callback) {
            Objects.requireNonNull(callback, "callback == null");
            //delegate是在實(shí)例化ExecutorCallbackCall時(shí)傳遞的第二個(gè)參數(shù),對(duì)象為OkHttpCall,也就是說這里enqueue()又委托給了OkHttpCall來執(zhí)行
            this.delegate.enqueue(new Callback<T>() {
                public void onResponse(Call<T> call, Response<T> response) {
                //在Android環(huán)境中運(yùn)行callbackExecutor默認(rèn)為MainThreadExecutor,當(dāng)網(wǎng)絡(luò)請(qǐng)求成功,執(zhí)行切回到主線程中,回調(diào)客戶端的callback對(duì)象的onResponse()方法
                    ExecutorCallbackCall.this.callbackExecutor.execute(() -> {
                        if (ExecutorCallbackCall.this.delegate.isCanceled()) {
                            callback.onFailure(ExecutorCallbackCall.this, new IOException("Canceled"));
                        } else {
                            callback.onResponse(ExecutorCallbackCall.this, response);
                        }

                    });
                }

                public void onFailure(Call<T> call, Throwable t) {
                    //失敗同樣也會(huì)切換到主線程去回調(diào)callback的onFailure()
                    ExecutorCallbackCall.this.callbackExecutor.execute(() -> {
                        callback.onFailure(ExecutorCallbackCall.this, t);
                    });
                }
            });
        }

        public boolean isExecuted() {
            return this.delegate.isExecuted();
        }

        public Response<T> execute() throws IOException {
            return this.delegate.execute();
        }

        public void cancel() {
            this.delegate.cancel();
        }

        public boolean isCanceled() {
            return this.delegate.isCanceled();
        }

        public Call<T> clone() {
            return new DefaultCallAdapterFactory.ExecutorCallbackCall(this.callbackExecutor, this.delegate.clone());
        }

        public Request request() {
            return this.delegate.request();
        }
    }

調(diào)用login的時(shí)候返回了一個(gè)Call,然后調(diào)用enqueue,我們就能看的出就是調(diào)用的這里(默認(rèn)),其實(shí)內(nèi)部調(diào)用的是delegate.enqueue(),也就是我們上文提到過得OkHttpCall的enqueue,調(diào)用okhttp3完成請(qǐng)求,拿到回調(diào)并且處理Response回調(diào)。

ExecutorCallbackCall.this.callbackExecutor

這里其實(shí)還有個(gè)這個(gè)東西需要說明下,callbackExecutor默認(rèn)是個(gè)啥,這里我們就可以追到

Android

  static final class Android extends Platform {
    Android() {
      super(Build.VERSION.SDK_INT >= 24);
    }

    @Override public Executor defaultCallbackExecutor() {
      return new MainThreadExecutor();
    }

    static class MainThreadExecutor implements Executor {
      private final Handler handler = new Handler(Looper.getMainLooper());

      @Override public void execute(Runnable r) {
        handler.post(r);
      }
    }
  }

真正調(diào)用接口的實(shí)現(xiàn)

OkHttpCall#enqueue

  @Override public void enqueue(final Callback<T> callback) {
    Objects.requireNonNull(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 {
          //創(chuàng)建okhttp3.Call
          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) {
          throwIfFatal(t);
          t.printStackTrace(); // TODO this is not great
        }
      }

      @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) {
          throwIfFatal(t);
          t.printStackTrace(); // TODO this is not great
        }
      }
    });
  }

接著追一下createRawCall()

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

RequestFactory#create()

  okhttp3.Request create(Object[] args) throws IOException {
    @SuppressWarnings("unchecked") // It is an error to invoke a method with the wrong arg types.
    ParameterHandler<Object>[] handlers = (ParameterHandler<Object>[]) parameterHandlers;

    int argumentCount = args.length;
    if (argumentCount != handlers.length) {
      throw new IllegalArgumentException("Argument count (" + argumentCount
          + ") doesn't match expected count (" + handlers.length + ")");
    }

    RequestBuilder requestBuilder = new RequestBuilder(httpMethod, baseUrl, relativeUrl,
        headers, contentType, hasBody, isFormEncoded, isMultipart);

    省略...

    return requestBuilder.get()
        .tag(Invocation.class, new Invocation(method, argumentList))
        .build();
  }

這里可以看到創(chuàng)建了個(gè)RequestBuilder,對(duì)一些屬性進(jìn)行了賦值,接著看get,

RequestBuilder#get()

  Request.Builder get() {
    HttpUrl url;
    HttpUrl.Builder urlBuilder = this.urlBuilder;
    if (urlBuilder != null) {
      url = urlBuilder.build();
    } else {
      // No query parameters triggered builder creation, just combine the relative URL and base URL.
      //noinspection ConstantConditions Non-null if urlBuilder is null.
      url = baseUrl.resolve(relativeUrl);
      if (url == null) {
        throw new IllegalArgumentException(
            "Malformed URL. Base: " + baseUrl + ", Relative: " + relativeUrl);
      }
    }

    RequestBody body = this.body;
    if (body == null) {
      // Try to pull from one of the builders.
      if (formBuilder != null) {
        body = formBuilder.build();
      } else if (multipartBuilder != null) {
        body = multipartBuilder.build();
      } else if (hasBody) {
        // Body is absent, make an empty body.
        body = RequestBody.create(null, new byte[0]);
      }
    }

    MediaType contentType = this.contentType;
    if (contentType != null) {
      if (body != null) {
        body = new ContentTypeOverridingRequestBody(body, contentType);
      } else {
        headersBuilder.add("Content-Type", contentType.toString());
      }
    }

    return requestBuilder
        .url(url)
        .headers(headersBuilder.build())
        .method(method, body);
  }

到這里我們就能看到Okhttp3的Request以及它的內(nèi)部類Builder了,到這里就終于揭開神秘面紗,打通Retrofit和OkHttp了。后面就是構(gòu)建OkHttp的request以及Call了,然后通過OkHttp的Call去請(qǐng)求,回調(diào)處理轉(zhuǎn)換類型。這里就不再細(xì)分下去了。對(duì)于OkHttp的原理感興趣的可以看我之前的博客。

總結(jié)一下上面的流程:

這里首先根據(jù)serviceMethod中關(guān)于login()方法的屬性以及解析的注解信息創(chuàng)建request請(qǐng)求對(duì)象,最后通過return callFactory.newCall(requestBuilder.build());
callFactory
默認(rèn)是OkHttpClient,我們就不在深入展示了,最終在其內(nèi)部返回的是一個(gè)RealCall,有興趣的可以進(jìn)去了解一下OkHttpClient源碼,到了這里,Retrofit的網(wǎng)絡(luò)請(qǐng)求底層便顯露在我們眼前,從這里我們就可以看到,Retrofit使用的網(wǎng)絡(luò)底層為OkHttp
接下來退回到enqueue()方法體內(nèi),之后調(diào)用call(RealCall)對(duì)象的enqueue()來處理網(wǎng)絡(luò)請(qǐng)求了,至于之后的事情,就是OkHttp底層要做的了。
最后我們使用RealCall調(diào)用enqueue()傳入的Callback對(duì)象,Callback的onResponse通過parseResponse()完成數(shù)據(jù)轉(zhuǎn)換。成功回調(diào)onResponse,失敗回調(diào)onFailure(),最后客戶端就可以看到網(wǎng)絡(luò)的訪問狀況了。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容