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

Retrofit網(wǎng)絡請求和響應處理重點分析講解

 更新時間:2023年03月10日 11:17:07   作者:萌動小彩筆  
這篇文章主要介紹了Retrofit網(wǎng)絡請求和響應處理重點分析,在使用?Retrofit發(fā)起網(wǎng)絡請求時,我們可以通過定義一個接口并使用Retrofit的注解來描述這個接口中的請求,Retrofit會自動生成一個實現(xiàn)該接口的代理對象

在上一篇文章中,我們詳細分析了 Retrofit 中的注解解析和動態(tài)代理實現(xiàn),本篇文章將繼續(xù)深入研究 Retrofit 的核心源碼,重點分析 Retrofit 如何進行網(wǎng)絡請求和響應處理。

網(wǎng)絡請求

在使用 Retrofit 發(fā)起網(wǎng)絡請求時,我們可以通過定義一個接口并使用 Retrofit 的注解來描述這個接口中的請求,Retrofit 會自動生成一個實現(xiàn)該接口的代理對象。當我們調用這個代理對象的方法時,Retrofit 會根據(jù)注解的描述構建一個 Request 對象,并使用 OkHttp 將這個 Request 發(fā)送出去。

在 Retrofit 中,我們可以通過 Retrofit#executeRetrofit#enqueue 方法來發(fā)送請求。這兩個方法的區(qū)別在于,execute 方法會阻塞當前線程直到請求完成,而 enqueue 方法會將請求加入到 OkHttp 的請求隊列中,并在請求完成時通過回調通知我們。

我們先來看一下 execute 方法的實現(xiàn):

public <T> T execute(Call<T> call) throws IOException {
  Utils.validateServiceInterface(call.request().tag(), call.request().url().toString());
  return (T) callAdapter(call, call.request().tag()).adapt(call).execute();
}

在這個方法中,首先會對接口進行校驗,確保這個接口是有效的。然后我們會根據(jù)請求的 Tag 和 URL 來獲取適配器callAdapter,并使用適配器來執(zhí)行請求。

適配器的作用是將請求的參數(shù)適配成 OkHttp 能夠識別的形式,并將 OkHttp 的響應適配成我們需要的形式。Retrofit 提供了一系列的適配器,包括 Call 適配器、RxJava 適配器、CompletableFuture 適配器等。

我們來看一下 callAdapter 方法的實現(xiàn):

private CallAdapter<?, ?> callAdapter(Call<?> call, Object tag) {
  Type responseType = call.request().method().equals("HEAD")
      ? Void.class
      : getParameterUpperBound(0, (ParameterizedType) call.request().tag());
  return callAdapter(tag, responseType);
}

在這個方法中,我們首先根據(jù)請求的方法來判斷響應的類型,如果是 HEAD 方法,那么響應的類型就是 Void;否則我們會通過反射來獲取請求的響應類型,并使用這個響應類型來獲取適配器。

獲取適配器的方法是 callAdapter

public <R, T> CallAdapter<R, T> callAdapter(Object tag, Type returnType) {
  // ...
  for (CallAdapter.Factory factory : adapterFactories) {
    CallAdapter<?, ?> adapter = factory.get(returnType, annotations, this);
    if (adapter != null) {
      return (CallAdapter<R, T>) adapter;
    }
  }
  // ...
}

在這個方法中,我們會遍歷所有的適配器工廠,嘗試獲取適配器。在獲取適配器時,我們會將請求的響應類型、注解和 Retrofit 實例作為參數(shù)傳入。每個適配器工廠都會判斷這些參數(shù)是否符合自己的適配條件,如果符合,就返回一個適配器實例,否則返回 null。在遍歷完所有的適配器工廠之后,如果還沒有獲取到適配器,那么就會拋出一個異常。

獲取到適配器之后,我們就可以使用適配器來執(zhí)行請求了。在適配器中,我們會將請求參數(shù)轉換成 OkHttp 的 Request 對象,并將 OkHttp 的 Response 對象轉換成我們需要的響應類型。具體的實現(xiàn)可以參考 Retrofit 提供的 CallAdapter 接口。

對于 enqueue 方法,我們可以先來看一下 enqueue 方法的實現(xiàn):

public <T> void enqueue(Call<T> call, Callback<T> callback) {
  Utils.validateServiceInterface(call.request().tag(), call.request().url().toString());
  callAdapter(call, call.request().tag()).adapt(call).enqueue(new CallbackRunnable<>(callback));
}

在這個方法中,我們首先進行接口校驗,然后根據(jù)請求的 Tag 和 URL 來獲取適配器,并使用適配器來執(zhí)行請求。不同的是,在 enqueue 方法中,我們將一個 Callback 對象作為參數(shù)傳入適配器的 enqueue 方法中,以便在請求完成后回調通知我們。

在適配器中,我們可以看到 enqueue 方法的實現(xiàn):

public void enqueue(final Callback<T> callback) {
  delegate.enqueue(new Callback<Response<T>>() {
    @Override public void onResponse(Call<Response<T>> call, Response<Response<T>> response) {
      Response<T> body;
      try {
        body = response.body();
      } catch (Throwable t) {
        if (response.code() == 204) {
          body = null;
        } else {
          callback.onFailure(call, t);
          return;
        }
      }
      if (response.isSuccessful()) {
        callback.onResponse(call, Response.success(body, response.raw()));
      } else {
        callback.onFailure(call, Response.error(response.errorBody(), response.raw()));
      }
    }
    @Override public void onFailure(Call<Response<T>> call, Throwable t) {
      callback.onFailure(call, t);
    }
  });
}

在這個方法中,我們會將傳入的 Callback 對象轉換成一個 Callback<Response<T>> 對象,并使用這個對象來調用 OkHttp 的 enqueue 方法。在請求完成后,我們會將 OkHttp 的 Response 對象轉換成 Retrofit 的 Response 對象,并根據(jù)響應碼來判斷請求的結果。如果響應碼表示請求成功,那么我們就調用 Callback 對象的 onResponse 方法;否則就調用 Callback 對象的 onFailure 方法。

響應處理

在 Retrofit 中,我們可以通過定義一個接口并使用注解來描述我們期望的請求格式和響應格式。例如,我們可以通過 @GET 注解來描述一個 GET 請求,使用 @Query 注解來描述請求參數(shù),使用 @Body 注解來描述請求體,使用 @Headers 注解來描述請求頭等。

在執(zhí)行請求時,Retrofit 會根據(jù)這些注解來自動生成一個對應的請求對象,并將請求對象轉換成 OkHttp 的 Request 對象。在接收響應時,Retrofit 會將 OkHttp 的 Response 對象轉換成一個對應的響應對象,并將響應對象中的數(shù)據(jù)轉換成我們需要的數(shù)據(jù)類型。這些轉換工作是通過 Retrofit 的轉換器來完成的,Retrofit 中默認提供了兩個轉換器:GsonConverterFactoryJacksonConverterFactory。我們也可以自定義一個轉換器來實現(xiàn)我們期望的數(shù)據(jù)轉換。

在 Retrofit 類的構造方法中,我們可以看到 Retrofit 默認使用了 Platform.get() 方法來獲取當前運行平臺的默認轉換器工廠,并將其添加到 converterFactories 中。然后,我們可以使用 addConverterFactory 方法來添加自定義的轉換器工廠。

public Retrofit(Builder builder) {
  // ...
  if (builder.converterFactories == null) {
    converterFactories.add(Platform.get().defaultConverterFactory());
  } else {
    converterFactories.addAll(builder.converterFactories);
  }
  // ...
}
public interface Platform {
  // ...
  Converter.Factory defaultConverterFactory();
}

execute方法中,我們會調用適配器的 adapt 方法來執(zhí)行請求,并將返回的 Call 對象轉換成一個響應對象。在轉換過程中,我們會根據(jù)響應類型來選擇對應的轉換器來進行轉換。具體的轉換實現(xiàn)可以參考 Retrofit 提供的 Converter 接口和 Converter.Factory 接口。

public <T> T execute(Call<T> call) throws IOException {
  // ...
  Response<T> response = call.execute();
  if (response.isSuccessful()) {
    return response.body();
  } else {
    Converter<ResponseBody, ErrorResponse> converter = retrofit.responseBodyConverter(
        ErrorResponse.class, new Annotation[0]);
    throw new ApiException(converter.convert(response.errorBody()));
  }
}
@SuppressWarnings("unchecked") // Single-interface proxy creation guarded by parameter safety.
public <T> T adapt(Call<T> call) {
  return (T) new OkHttpCall<>(requestFactory, callFactory, converter, call);
}
public <T> Converter<ResponseBody, T> responseBodyConverter(Type type, Annotation[] annotations) {
  return nextResponseBodyConverter(null, type, annotations);
}
public <T> Converter<ResponseBody, T> nextResponseBodyConverter(
    @Nullable Converter.Factory skipPast, Type type, Annotation[] annotations) {
  Objects.requireNonNull(type, "type == null");
  Objects.requireNonNull(annotations, "annotations == null");
  int start = converterFactories.indexOf(skipPast) + 1;
  for (int i = start, count = converterFactories.size(); i < count; i++) {
    Converter<ResponseBody, ?> converter =
        converterFactories.get(i).responseBodyConverter(type, annotations, this);
    if (converter != null) {
      return (Converter<ResponseBody, T>) converter;
    }
  }
  throw new IllegalArgumentException(
      "Could not locate ResponseBody converter for " + type + " with annotations " + Arrays.toString(annotations));
}

以上是 Retrofit 中處理響應的核心代碼。當我們執(zhí)行一個請求時,Retrofit 會先將請求轉換成 OkHttp 的 Request 對象并發(fā)送出去,然后等待響應返回。當響應返回時,Retrofit 會將響應轉換成一個響應對象,并將響應對象中的數(shù)據(jù)轉換成我們期望的數(shù)據(jù)類型。這個過程中,我們可以使用 Retrofit 提供的轉換器來自定義數(shù)據(jù)的轉換規(guī)則。

下面是一個示例,演示了如何使用 Retrofit 來發(fā)送一個 GET 請求并將響應中的 JSON 數(shù)據(jù)轉換成一個 Java 對象:

public interface ApiService {
  @GET("users/{user}/repos")
  Call<List<Repo>> listRepos(@Path("user") String user);
}
Retrofit retrofit = new Retrofit.Builder()
    .baseUrl("https://api.github.com/")
    .addConverterFactory(GsonConverterFactory.create())
    .build();
ApiService apiService = retrofit.create(ApiService.class);
Call<List<Repo>> call = apiService.listRepos("smallmarker");
List<Repo> repos = call.execute().body();

在上面的示例中,我們首先使用 Retrofit 構建器創(chuàng)建一個 Retrofit 實例,并指定了請求的基礎 URL 和轉換器工廠。然后,我們通過調用 create 方法來創(chuàng)建一個 ApiService 的代理對象。最后,我們調用 listRepos 方法來發(fā)送一個 GET 請求。

在上面的示例中,我們使用了 Retrofit 的 GsonConverterFactory 來將響應體中的 JSON 數(shù)據(jù)轉換成 Java 對象。具體實現(xiàn)可以查看 Retrofit 提供的 GsonConverterFactory 類。

public final class GsonConverterFactory extends Converter.Factory {
  private final Gson gson;
  private GsonConverterFactory(Gson gson) {
    this.gson = gson;
  }
  public static GsonConverterFactory create() {
    return create(new Gson());
  }
  public static GsonConverterFactory create(Gson gson) {
    if (gson == null) throw new NullPointerException("gson == null");
    return new GsonConverterFactory(gson);
  }
  @Override
  public @Nullable Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations, Retrofit retrofit) {
    TypeAdapter<?> adapter = gson.getAdapter(TypeToken.get(type));
    return new GsonResponseBodyConverter<>(gson, adapter);
  }
  @Override
  public @Nullable Converter<?, RequestBody> requestBodyConverter(Type type, Annotation[] parameterAnnotations,
                                                                  Annotation[] methodAnnotations, Retrofit retrofit) {
    TypeAdapter<?> adapter = gson.getAdapter(TypeToken.get(type));
    return new GsonRequestBodyConverter<>(gson, adapter);
  }
}

可以看到,GsonConverterFactory 繼承了 Retrofit 的 Converter.Factory 類,并重寫了其中的 responseBodyConverter 方法和 requestBodyConverter 方法。在 responseBodyConverter 方法中,我們將響應體中的 JSON 數(shù)據(jù)轉換成 Java 對象,而在 requestBodyConverter 方法中,我們將 Java 對象轉換成請求體中的 JSON 數(shù)據(jù)。

除了 GsonConverterFactory 以外,Retrofit 還提供了其他的轉換器,如 JacksonConverterFactory、MoshiConverterFactory 等,我們可以根據(jù)需要選擇適合自己的轉換器。

總的來說,Retrofit 中網(wǎng)絡請求和響應處理的核心代碼非常簡潔明了。我們只需要通過定義接口來描述請求和響應,然后使用 Retrofit 的動態(tài)代理機制來將接口轉換成一個實際的實現(xiàn)類,并通過 Retrofit 的配置來指定請求和響應的轉換器即可。這種方式大大簡化了網(wǎng)絡請求的流程,使得我們可以更加專注于業(yè)務邏輯的處理。

到此這篇關于Retrofit網(wǎng)絡請求和響應處理重點分析講解的文章就介紹到這了,更多相關Retrofit網(wǎng)絡請求和響應處理內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • Android中的Bitmap的詳細介紹

    Android中的Bitmap的詳細介紹

    本篇文章主要介紹了Android中的Bitmap,是Windows標準格式圖形文件,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-01-01
  • Android項目中引用本地aar文件的方法

    Android項目中引用本地aar文件的方法

    這篇文章主要介紹了Android項目中引用本地aar文件的方法,本文講解了什么是aar文件、導出aar文件方法、引用本地的aar文件方法等內容,需要的朋友可以參考下
    2015-05-05
  • Android中ImageView的使用方法

    Android中ImageView的使用方法

    這篇文章主要為大家詳細介紹了Android中ImageView的使用方法,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-05-05
  • Android?Flutter實現(xiàn)任意拖動的控件

    Android?Flutter實現(xiàn)任意拖動的控件

    使用flutter開發(fā)是需要控件能拖動,比如畫板中的元素,或者工具條等,所以本文為大家準備了Flutter實現(xiàn)任意拖動控件的示例代碼,希望對大家有所幫助
    2023-07-07
  • Android監(jiān)聽鍵盤狀態(tài)獲取鍵盤高度的實現(xiàn)方法

    Android監(jiān)聽鍵盤狀態(tài)獲取鍵盤高度的實現(xiàn)方法

    這篇文章主要給大家介紹了關于Android監(jiān)聽鍵盤狀態(tài)獲取鍵盤高度的實現(xiàn)方法,文中通過示例代碼介紹的非常詳細,對各位Android開發(fā)者們具有一定的參考學習價值,需要的朋友們下面來一起學習學習吧
    2019-12-12
  • Android仿微信微博多圖展示效果

    Android仿微信微博多圖展示效果

    這篇文章主要為大家詳細介紹了Android仿微信微博多圖展示效果,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-02-02
  • Compose自定義View實現(xiàn)宇智波斑寫輪眼

    Compose自定義View實現(xiàn)宇智波斑寫輪眼

    這篇文章主要為大家介紹了Compose自定義View實現(xiàn)宇智波斑寫輪眼示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-02-02
  • android實現(xiàn)數(shù)獨游戲機器人

    android實現(xiàn)數(shù)獨游戲機器人

    這篇文章主要為大家詳細介紹了android實現(xiàn)數(shù)獨游戲機器人,文中安裝步驟介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-03-03
  • android仿京東商品屬性篩選功能

    android仿京東商品屬性篩選功能

    這篇文章主要為大家詳細介紹了android仿京東商品屬性篩選功能,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-12-12
  • Android實現(xiàn)根據(jù)評分添加星級條

    Android實現(xiàn)根據(jù)評分添加星級條

    這篇文章主要介紹了Android實現(xiàn)根據(jù)評分添加星級條,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2019-10-10

最新評論