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

Retrofit網(wǎng)絡(luò)請(qǐng)求和響應(yīng)處理重點(diǎn)分析講解

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

在上一篇文章中,我們?cè)敿?xì)分析了 Retrofit 中的注解解析和動(dòng)態(tài)代理實(shí)現(xiàn),本篇文章將繼續(xù)深入研究 Retrofit 的核心源碼,重點(diǎn)分析 Retrofit 如何進(jìn)行網(wǎng)絡(luò)請(qǐng)求和響應(yīng)處理。

網(wǎng)絡(luò)請(qǐng)求

在使用 Retrofit 發(fā)起網(wǎng)絡(luò)請(qǐng)求時(shí),我們可以通過(guò)定義一個(gè)接口并使用 Retrofit 的注解來(lái)描述這個(gè)接口中的請(qǐng)求,Retrofit 會(huì)自動(dòng)生成一個(gè)實(shí)現(xiàn)該接口的代理對(duì)象。當(dāng)我們調(diào)用這個(gè)代理對(duì)象的方法時(shí),Retrofit 會(huì)根據(jù)注解的描述構(gòu)建一個(gè) Request 對(duì)象,并使用 OkHttp 將這個(gè) Request 發(fā)送出去。

在 Retrofit 中,我們可以通過(guò) Retrofit#executeRetrofit#enqueue 方法來(lái)發(fā)送請(qǐng)求。這兩個(gè)方法的區(qū)別在于,execute 方法會(huì)阻塞當(dāng)前線程直到請(qǐng)求完成,而 enqueue 方法會(huì)將請(qǐng)求加入到 OkHttp 的請(qǐng)求隊(duì)列中,并在請(qǐng)求完成時(shí)通過(guò)回調(diào)通知我們。

我們先來(lái)看一下 execute 方法的實(shí)現(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();
}

在這個(gè)方法中,首先會(huì)對(duì)接口進(jìn)行校驗(yàn),確保這個(gè)接口是有效的。然后我們會(huì)根據(jù)請(qǐng)求的 Tag 和 URL 來(lái)獲取適配器callAdapter,并使用適配器來(lái)執(zhí)行請(qǐng)求。

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

我們來(lái)看一下 callAdapter 方法的實(shí)現(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);
}

在這個(gè)方法中,我們首先根據(jù)請(qǐng)求的方法來(lái)判斷響應(yīng)的類型,如果是 HEAD 方法,那么響應(yīng)的類型就是 Void;否則我們會(huì)通過(guò)反射來(lái)獲取請(qǐng)求的響應(yīng)類型,并使用這個(gè)響應(yīng)類型來(lái)獲取適配器。

獲取適配器的方法是 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;
    }
  }
  // ...
}

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

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

對(duì)于 enqueue 方法,我們可以先來(lái)看一下 enqueue 方法的實(shí)現(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));
}

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

在適配器中,我們可以看到 enqueue 方法的實(shí)現(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);
    }
  });
}

在這個(gè)方法中,我們會(huì)將傳入的 Callback 對(duì)象轉(zhuǎn)換成一個(gè) Callback<Response<T>> 對(duì)象,并使用這個(gè)對(duì)象來(lái)調(diào)用 OkHttp 的 enqueue 方法。在請(qǐng)求完成后,我們會(huì)將 OkHttp 的 Response 對(duì)象轉(zhuǎn)換成 Retrofit 的 Response 對(duì)象,并根據(jù)響應(yīng)碼來(lái)判斷請(qǐng)求的結(jié)果。如果響應(yīng)碼表示請(qǐng)求成功,那么我們就調(diào)用 Callback 對(duì)象的 onResponse 方法;否則就調(diào)用 Callback 對(duì)象的 onFailure 方法。

響應(yīng)處理

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

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

在 Retrofit 類的構(gòu)造方法中,我們可以看到 Retrofit 默認(rèn)使用了 Platform.get() 方法來(lái)獲取當(dāng)前運(yùn)行平臺(tái)的默認(rèn)轉(zhuǎn)換器工廠,并將其添加到 converterFactories 中。然后,我們可以使用 addConverterFactory 方法來(lái)添加自定義的轉(zhuǎn)換器工廠。

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方法中,我們會(huì)調(diào)用適配器的 adapt 方法來(lái)執(zhí)行請(qǐng)求,并將返回的 Call 對(duì)象轉(zhuǎn)換成一個(gè)響應(yīng)對(duì)象。在轉(zhuǎn)換過(guò)程中,我們會(huì)根據(jù)響應(yīng)類型來(lái)選擇對(duì)應(yīng)的轉(zhuǎn)換器來(lái)進(jìn)行轉(zhuǎn)換。具體的轉(zhuǎn)換實(shí)現(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 中處理響應(yīng)的核心代碼。當(dāng)我們執(zhí)行一個(gè)請(qǐng)求時(shí),Retrofit 會(huì)先將請(qǐng)求轉(zhuǎn)換成 OkHttp 的 Request 對(duì)象并發(fā)送出去,然后等待響應(yīng)返回。當(dāng)響應(yīng)返回時(shí),Retrofit 會(huì)將響應(yīng)轉(zhuǎn)換成一個(gè)響應(yīng)對(duì)象,并將響應(yīng)對(duì)象中的數(shù)據(jù)轉(zhuǎn)換成我們期望的數(shù)據(jù)類型。這個(gè)過(guò)程中,我們可以使用 Retrofit 提供的轉(zhuǎn)換器來(lái)自定義數(shù)據(jù)的轉(zhuǎn)換規(guī)則。

下面是一個(gè)示例,演示了如何使用 Retrofit 來(lái)發(fā)送一個(gè) GET 請(qǐng)求并將響應(yīng)中的 JSON 數(shù)據(jù)轉(zhuǎn)換成一個(gè) Java 對(duì)象:

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 構(gòu)建器創(chuàng)建一個(gè) Retrofit 實(shí)例,并指定了請(qǐng)求的基礎(chǔ) URL 和轉(zhuǎn)換器工廠。然后,我們通過(guò)調(diào)用 create 方法來(lái)創(chuàng)建一個(gè) ApiService 的代理對(duì)象。最后,我們調(diào)用 listRepos 方法來(lái)發(fā)送一個(gè) GET 請(qǐng)求。

在上面的示例中,我們使用了 Retrofit 的 GsonConverterFactory 來(lái)將響應(yīng)體中的 JSON 數(shù)據(jù)轉(zhuǎn)換成 Java 對(duì)象。具體實(shí)現(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 類,并重寫(xiě)了其中的 responseBodyConverter 方法和 requestBodyConverter 方法。在 responseBodyConverter 方法中,我們將響應(yīng)體中的 JSON 數(shù)據(jù)轉(zhuǎn)換成 Java 對(duì)象,而在 requestBodyConverter 方法中,我們將 Java 對(duì)象轉(zhuǎn)換成請(qǐng)求體中的 JSON 數(shù)據(jù)。

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

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

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

相關(guān)文章

  • Android中的Bitmap的詳細(xì)介紹

    Android中的Bitmap的詳細(xì)介紹

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

    Android項(xiàng)目中引用本地aar文件的方法

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

    Android中ImageView的使用方法

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

    Android?Flutter實(shí)現(xiàn)任意拖動(dòng)的控件

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

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

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

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

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

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

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

    android實(shí)現(xiàn)數(shù)獨(dú)游戲機(jī)器人

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

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

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

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

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

最新評(píng)論