欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Android Retrofit原理深入探索

 更新時(shí)間:2022年11月03日 10:31:25   作者:明智的健哥  
Retrofit 是一個(gè) RESTful 的 HTTP 網(wǎng)絡(luò)請求框架的封裝,網(wǎng)絡(luò)請求的工作本質(zhì)上是 OkHttp 完成,而 Retrofit 僅負(fù)責(zé) 網(wǎng)絡(luò)請求接口的封裝

序章

首先引入依賴

    implementation 'com.squareup.retrofit2:retrofit:2.9.0'

在原理之前,我們先來回憶一下Retrofit的基本使用

1、定義接口

interface MyService {
    @GET("gallery/{imageType}/response")
    fun getImages(@Path("imageType") imageType: String): Call<List<String>>
}

2、構(gòu)建Retrofit,創(chuàng)建網(wǎng)絡(luò)請求接口類實(shí)例

        val retrofit = Retrofit.Builder()
            .baseUrl(BASE_URL)
            .build()
        val myService = retrofit.create(MyService::class.java)

3、生成Call,執(zhí)行請求

        val resp = myService.getImages("banner")
        resp.enqueue(object : Callback<List<String>> {
            override fun onResponse(call: Call<List<String>>, response: Response<List<String>>) {
                TODO("Not yet implemented")
            }
            override fun onFailure(call: Call<List<String>>, t: Throwable) {
                TODO("Not yet implemented")
            }
        })

這樣一個(gè)基本的網(wǎng)絡(luò)請求就搞定了,使用很簡潔,正是因?yàn)槠鋬?nèi)部使用了大量的設(shè)計(jì)模式和優(yōu)秀的架構(gòu)設(shè)計(jì),才得以使其如此方便地進(jìn)行網(wǎng)絡(luò)請求,下面我們就一起來探索探索Retrofit的設(shè)計(jì)之美。

Retrofit構(gòu)建過程

使用了建造者模式通過內(nèi)部靜態(tài)類Builder構(gòu)建一個(gè)Retrofit實(shí)例,這里只列出了部分方法,其他類似

public static final class Builder {
    private final Platform platform;
    // 網(wǎng)絡(luò)請求工廠,工廠方法模式
    private @Nullable okhttp3.Call.Factory callFactory;
    // 網(wǎng)絡(luò)請求地址
    private @Nullable HttpUrl baseUrl;
    // 數(shù)據(jù)轉(zhuǎn)換器工廠的集合
    private final List<Converter.Factory> converterFactories = new ArrayList<>();
    // 網(wǎng)絡(luò)請求適配器工廠的集合,默認(rèn)是ExecutorCallAdapterFactory
    private final List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>();
    // 回調(diào)方法執(zhí)行器,用于切換線程
    private @Nullable Executor callbackExecutor;
    // 一個(gè)開關(guān),為true則會緩存創(chuàng)建的ServiceMethod
    private boolean validateEagerly;
    //......
    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;
    }
    // 將一個(gè)含有Gson對象實(shí)例的GsonConverterFactory放入數(shù)據(jù)轉(zhuǎn)換器工廠
    public Builder addConverterFactory(Converter.Factory factory) {
      converterFactories.add(Objects.requireNonNull(factory, "factory == null"));
      return this;
    }
    //......
}

通過build,我們上面Builder類中的參數(shù)對象都配置到了Retrofit對象中。

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

創(chuàng)建網(wǎng)絡(luò)請求接口實(shí)例過程

使用動態(tài)代理的方式拿到所有注解配置后,創(chuàng)建網(wǎng)絡(luò)請求接口實(shí)例。

  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);
                }
                args = args != null ? args : emptyArgs;
                return platform.isDefaultMethod(method)
                    ? platform.invokeDefaultMethod(method, service, proxy, args)
                    : loadServiceMethod(method).invoke(args);
              }
            });
  }

跟蹤 loadServiceMethod,parseAnnotations解析注解配置得到ServiceMethod,然后加入到serviceMethodCache緩存中,是一個(gè)ConcurrentHashMap。

  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;
  }
abstract class ServiceMethod<T> {
  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);
  }
  abstract @Nullable T invoke(Object[] args);
}

執(zhí)行請求過程

  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)建一個(gè)OkHttp的Request對象請求
          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 {
              // 解析網(wǎng)絡(luò)請求返回的數(shù)據(jù)
              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
            }
          }
        });
  }
  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();
    int code = rawResponse.code();
    // 根據(jù)響應(yīng)返回的狀態(tài)碼進(jìn)行處理 
    if (code < 200 || code >= 300) {
      try {
        // Buffer the entire body to avoid future I/O.
        ResponseBody bufferedBody = Utils.buffer(rawBody);
        return Response.error(bufferedBody, rawResponse);
      } finally {
        rawBody.close();
      }
    }
    if (code == 204 || code == 205) {
      rawBody.close();
      return Response.success(null, rawResponse);
    }
    ExceptionCatchingResponseBody catchingBody = new ExceptionCatchingResponseBody(rawBody);
    try {
      // 將響應(yīng)體轉(zhuǎn)為Java對象
      T body = responseConverter.convert(catchingBody);
      return Response.success(body, rawResponse);
    } catch (RuntimeException e) {
      // If the underlying source threw an exception, propagate that rather than indicating it was
      // a runtime exception.
      catchingBody.throwIfCaught();
      throw e;
    }
  }

總結(jié)

首先,使用建造者模式通過Builder構(gòu)建一個(gè)Retrofit實(shí)例,Builder類中的參數(shù)對象都配置到Retrofit對象中,然后使用動態(tài)代理的方式拿到所有注解配置后,創(chuàng)建網(wǎng)絡(luò)請求接口實(shí)例,生成OkHttp請求,通過callAdapterFactory找到對應(yīng)的執(zhí)行器,比如RxJava2CallAdapterFactory,最后通過ConverterFactory將返回?cái)?shù)據(jù)解析成JavaBean,使用者只需關(guān)心請求參數(shù),內(nèi)部實(shí)現(xiàn)由Retrofit封裝完成,底層請求還是基于okhttp實(shí)現(xiàn)的。

到此這篇關(guān)于Android Retrofit原理深入探索的文章就介紹到這了,更多相關(guān)Android Retrofit內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評論