欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 新闻 > 资讯 > Retrofit 框架数据转换模块深入源码分析(四)

Retrofit 框架数据转换模块深入源码分析(四)

2025/5/21 11:02:24 来源:https://blog.csdn.net/qq_19641309/article/details/147295615  浏览:    关键词:Retrofit 框架数据转换模块深入源码分析(四)

Retrofit 框架数据转换模块深入源码分析

一、引言

在现代的 Android 和 Java 开发中,网络请求是必不可少的一部分。Retrofit 作为一个强大的网络请求框架,以其简洁的 API 和高度的可定制性受到了广泛的欢迎。数据转换模块是 Retrofit 框架中至关重要的一部分,它负责将请求参数序列化为 HTTP 请求体,以及将 HTTP 响应体反序列化为 Java 对象。通过对 Retrofit 数据转换模块的源码分析,我们可以深入了解其工作原理,从而更好地使用和扩展这个框架。

二、数据转换模块的核心概念

2.1 Converter 接口

Converter 接口是数据转换模块的核心接口,它定义了数据转换的基本方法。以下是 Converter 接口的源码:

java

// Converter 接口定义了数据转换的基本方法
public interface Converter<F, T> {// 将输入类型 F 转换为输出类型 TT convert(F value) throws IOException;
}

这个接口非常简单,只定义了一个 convert 方法,用于将输入类型 F 转换为输出类型 T。在实际应用中,F 通常是 ResponseBody(用于响应体转换)或请求参数类型(用于请求体转换),T 则是 Java 对象类型。

2.2 Converter.Factory 抽象类

Converter.Factory 抽象类是用于创建 Converter 对象的工厂类。以下是其源码:

java

// 工厂类,用于创建 Converter 对象
public abstract static class Factory {// 创建请求体转换器,用于将请求参数转换为 RequestBodypublic @Nullable Converter<?, RequestBody> requestBodyConverter(Type type,Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) {return null;}// 创建响应体转换器,用于将 ResponseBody 转换为 Java 对象public @Nullable Converter<ResponseBody, ?> responseBodyConverter(Type type,Annotation[] annotations, Retrofit retrofit) {return null;}// 创建字符串转换器,用于将对象转换为字符串public @Nullable Converter<?, String> stringConverter(Type type, Annotation[] annotations,Retrofit retrofit) {return null;}
}

Converter.Factory 抽象类提供了三个方法,分别用于创建请求体转换器、响应体转换器和字符串转换器。这些方法的默认实现返回 null,具体的实现由子类完成。

2.3 Retrofit 类中的相关方法

Retrofit 类是 Retrofit 框架的核心类,它包含了与数据转换模块相关的方法。以下是部分相关源码:

java

public final class Retrofit {// 转换器工厂列表private final List<Converter.Factory> converterFactories;Retrofit(okhttp3.Call.Factory callFactory, HttpUrl baseUrl,List<Converter.Factory> converterFactories, List<CallAdapter.Factory> callAdapterFactories,Executor callbackExecutor, boolean validateEagerly) {this.callFactory = callFactory;this.baseUrl = baseUrl;// 保存转换器工厂列表this.converterFactories = unmodifiableList(converterFactories);this.callAdapterFactories = unmodifiableList(callAdapterFactories);this.callbackExecutor = callbackExecutor;this.validateEagerly = validateEagerly;}// 创建响应转换器private static <T> Converter<ResponseBody, T> createResponseConverter(Retrofit retrofit, Method method, Type responseType) {Annotation[] annotations = method.getAnnotations();try {// 遍历转换器工厂列表,查找合适的转换器工厂for (Converter.Factory factory : retrofit.converterFactories()) {// 调用工厂的 responseBodyConverter 方法创建响应体转换器Converter<ResponseBody, ?> converter = factory.responseBodyConverter(responseType, annotations, retrofit);if (converter != null) {// 找到合适的转换器,返回return (Converter<ResponseBody, T>) converter;}}} catch (RuntimeException e) {throw methodError(method, e, "Unable to create converter for %s", responseType);}throw methodError(method, "Could not locate response converter for %s.", responseType);}// 创建请求体转换器private static <T> Converter<T, RequestBody> createRequestBodyConverter(Retrofit retrofit, Method method, Type requestType, Annotation[] parameterAnnotations) {Annotation[] methodAnnotations = method.getAnnotations();try {// 遍历转换器工厂列表,查找合适的转换器工厂for (Converter.Factory factory : retrofit.converterFactories()) {// 调用工厂的 requestBodyConverter 方法创建请求体转换器Converter<?, RequestBody> converter = factory.requestBodyConverter(requestType, parameterAnnotations, methodAnnotations, retrofit);if (converter != null) {// 找到合适的转换器,返回return (Converter<T, RequestBody>) converter;}}} catch (RuntimeException e) {throw methodError(method, e, "Unable to create converter for %s", requestType);}throw methodError(method, "Could not locate request body converter for %s.", requestType);}
}

Retrofit 类中保存了一个 converterFactories 列表,用于存储所有的转换器工厂。createResponseConverter 方法和 createRequestBodyConverter 方法分别用于创建响应体转换器和请求体转换器,它们会遍历 converterFactories 列表,调用每个工厂的相应方法,直到找到合适的转换器为止。

三、常见的转换器工厂实现

3.1 GsonConverterFactory

GsonConverterFactory 是 Retrofit 中常用的转换器工厂,它使用 Gson 库来进行 JSON 数据的序列化和反序列化。以下是其源码分析:

java

// Gson 转换器工厂类
public final class GsonConverterFactory extends Converter.Factory {private final Gson gson;private GsonConverterFactory(Gson gson) {this.gson = gson;}// 创建 GsonConverterFactory 实例public static GsonConverterFactory create() {return create(new Gson());}// 创建 GsonConverterFactory 实例,传入自定义的 Gson 实例public static GsonConverterFactory create(Gson gson) {return new GsonConverterFactory(gson);}// 创建响应体转换器@Overridepublic Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations, Retrofit retrofit) {return new GsonResponseBodyConverter<>(gson, type);}// 创建请求体转换器@Overridepublic Converter<?, RequestBody> requestBodyConverter(Type type, Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) {return new GsonRequestBodyConverter<>(gson, type);}
}// Gson 响应体转换器
final class GsonResponseBodyConverter<T> implements Converter<ResponseBody, T> {private final Gson gson;private final TypeAdapter<T> adapter;GsonResponseBodyConverter(Gson gson, Type type) {this.gson = gson;// 通过 Gson 获取指定类型的 TypeAdapter,用于解析 JSON 数据this.adapter = gson.getAdapter(TypeToken.get(type));}@Overridepublic T convert(ResponseBody value) throws IOException {// 创建 JsonReader 对象,用于读取响应体的字符流JsonReader jsonReader = gson.newJsonReader(value.charStream());try {// 使用 TypeAdapter 从 JsonReader 中读取数据并转换为指定类型return adapter.read(jsonReader);} finally {// 关闭响应体value.close();}}
}// Gson 请求体转换器
final class GsonRequestBodyConverter<T> implements Converter<T, RequestBody> {private static final MediaType MEDIA_TYPE = MediaType.get("application/json; charset=UTF-8");private static final Charset UTF_8 = Charset.forName("UTF-8");private final Gson gson;private final TypeAdapter<T> adapter;GsonRequestBodyConverter(Gson gson, Type type) {this.gson = gson;// 通过 Gson 获取指定类型的 TypeAdapter,用于将对象转换为 JSON 数据this.adapter = gson.getAdapter(TypeToken.get(type));}@Overridepublic RequestBody convert(T value) throws IOException {// 创建 ByteArrayOutputStream 用于存储序列化后的 JSON 数据ByteArrayOutputStream out = new ByteArrayOutputStream();// 创建 JsonWriter 对象,用于将对象以 JSON 格式写入输出流JsonWriter jsonWriter = gson.newJsonWriter(new OutputStreamWriter(out, UTF_8));try {// 使用 TypeAdapter 将对象写入 JsonWriteradapter.write(jsonWriter, value);// 刷新 JsonWriter 以确保所有数据都被写入输出流jsonWriter.close();} catch (IOException e) {// 捕获可能的 I/O 异常并重新抛出throw new AssertionError(e); // Writing to a buffer can't throw an IOException.}// 创建 OkHttp 的 RequestBody 对象,指定媒体类型和字节数组return RequestBody.create(MEDIA_TYPE, out.toByteArray());}
}
3.1.1 GsonConverterFactory 类

GsonConverterFactory 类实现了 Converter.Factory 抽象类,提供了 create 方法用于创建实例。responseBodyConverter 方法返回 GsonResponseBodyConverter 实例,用于将响应体转换为 Java 对象;requestBodyConverter 方法返回 GsonRequestBodyConverter 实例,用于将 Java 对象转换为请求体。

3.1.2 GsonResponseBodyConverter 类

GsonResponseBodyConverter 类实现了 Converter<ResponseBody, T> 接口,其 convert 方法使用 Gson 的 TypeAdapter 从 ResponseBody 中读取 JSON 数据并转换为指定类型的 Java 对象。

3.1.3 GsonRequestBodyConverter 类

GsonRequestBodyConverter 类实现了 Converter<T, RequestBody> 接口,其 convert 方法使用 Gson 的 TypeAdapter 将 Java 对象转换为 JSON 数据,并创建 RequestBody 对象。

3.2 ScalarsConverterFactory

ScalarsConverterFactory 用于处理基本数据类型(如 StringByteStringbyte[])的转换。以下是其源码分析:

java

// 标量转换器工厂类
public final class ScalarsConverterFactory extends Converter.Factory {private static final MediaType MEDIA_TYPE = MediaType.get("text/plain; charset=UTF-8");// 创建响应体转换器@Overridepublic Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations, Retrofit retrofit) {if (type == String.class) {return new StringResponseBodyConverter();}if (type == ByteString.class) {return new ByteStringResponseBodyConverter();}if (type == byte[].class) {return new ByteArrayResponseBodyConverter();}return null;}// 创建请求体转换器@Overridepublic Converter<?, RequestBody> requestBodyConverter(Type type, Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) {if (type == String.class) {return new StringRequestBodyConverter();}if (type == ByteString.class) {return new ByteStringRequestBodyConverter();}if (type == byte[].class) {return new ByteArrayRequestBodyConverter();}return null;}// 字符串响应体转换器static final class StringResponseBodyConverter implements Converter<ResponseBody, String> {@Overridepublic String convert(ResponseBody value) throws IOException {try {return value.string();} finally {value.close();}}}// ByteString 响应体转换器static final class ByteStringResponseBodyConverter implements Converter<ResponseBody, ByteString> {@Overridepublic ByteString convert(ResponseBody value) throws IOException {try {return value.source().readByteString();} finally {value.close();}}}// 字节数组响应体转换器static final class ByteArrayResponseBodyConverter implements Converter<ResponseBody, byte[]> {@Overridepublic byte[] convert(ResponseBody value) throws IOException {try {return value.bytes();} finally {value.close();}}}// 字符串请求体转换器static final class StringRequestBodyConverter implements Converter<String, RequestBody> {@Overridepublic RequestBody convert(String value) throws IOException {return RequestBody.create(MEDIA_TYPE, value);}}// ByteString 请求体转换器static final class ByteStringRequestBodyConverter implements Converter<ByteString, RequestBody> {@Overridepublic RequestBody convert(ByteString value) throws IOException {return RequestBody.create(MEDIA_TYPE, value);}}// 字节数组请求体转换器static final class ByteArrayRequestBodyConverter implements Converter<byte[], RequestBody> {@Overridepublic RequestBody convert(byte[] value) throws IOException {return RequestBody.create(MEDIA_TYPE, value);}}
}
3.2.1 ScalarsConverterFactory 类

ScalarsConverterFactory 类实现了 Converter.Factory 抽象类,responseBodyConverter 方法根据目标类型返回不同的响应体转换器,requestBodyConverter 方法根据源类型返回不同的请求体转换器。

3.2.2 具体的转换器类

StringResponseBodyConverterByteStringResponseBodyConverter 和 ByteArrayResponseBodyConverter 分别用于将响应体转换为 StringByteString 和 byte[] 类型;StringRequestBodyConverterByteStringRequestBodyConverter 和 ByteArrayRequestBodyConverter 分别用于将 StringByteString 和 byte[] 类型转换为请求体。

3.3 MoshiConverterFactory

MoshiConverterFactory 是基于 Moshi 库的转换器工厂,用于处理 JSON 数据的序列化和反序列化。以下是其源码分析:

java

// Moshi 转换器工厂类
public final class MoshiConverterFactory extends Converter.Factory {private final Moshi moshi;private final boolean lenient;private final boolean failOnUnknown;private final boolean serializeNulls;// 创建 MoshiConverterFactory 实例public static MoshiConverterFactory create() {return create(new Moshi.Builder().build());}// 创建 MoshiConverterFactory 实例,传入自定义的 Moshi 实例public static MoshiConverterFactory create(Moshi moshi) {return new MoshiConverterFactory(moshi, false, false, false);}private MoshiConverterFactory(Moshi moshi, boolean lenient, boolean failOnUnknown, boolean serializeNulls) {this.moshi = moshi;this.lenient = lenient;this.failOnUnknown = failOnUnknown;this.serializeNulls = serializeNulls;}// 创建响应体转换器@Overridepublic Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations, Retrofit retrofit) {JsonAdapter<?> adapter = moshi.adapter(type);if (lenient) {adapter = adapter.lenient();}if (failOnUnknown) {adapter = adapter.failOnUnknown();}if (serializeNulls) {adapter = adapter.serializeNulls();}return new MoshiResponseBodyConverter<>(adapter);}// 创建请求体转换器@Overridepublic Converter<?, RequestBody> requestBodyConverter(Type type, Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) {JsonAdapter<?> adapter = moshi.adapter(type);if (lenient) {adapter = adapter.lenient();}if (failOnUnknown) {adapter = adapter.failOnUnknown();}if (serializeNulls) {adapter = adapter.serializeNulls();}return new MoshiRequestBodyConverter<>(adapter);}
}// Moshi 响应体转换器
final class MoshiResponseBodyConverter<T> implements Converter<ResponseBody, T> {private final JsonAdapter<T> adapter;MoshiResponseBodyConverter(JsonAdapter<T> adapter) {this.adapter = adapter;}@Overridepublic T convert(ResponseBody value) throws IOException {try {return adapter.fromJson(value.source());} finally {value.close();}}
}// Moshi 请求体转换器
final class MoshiRequestBodyConverter<T> implements Converter<T, RequestBody> {private static final MediaType MEDIA_TYPE = MediaType.get("application/json; charset=UTF-8");private final JsonAdapter<T> adapter;MoshiRequestBodyConverter(JsonAdapter<T> adapter) {this.adapter = adapter;}@Overridepublic RequestBody convert(T value) throws IOException {Buffer buffer = new Buffer();adapter.toJson(buffer, value);return RequestBody.create(MEDIA_TYPE, buffer.readByteString());}
}
3.3.1 MoshiConverterFactory 类

MoshiConverterFactory 类实现了 Converter.Factory 抽象类,提供了 create 方法用于创建实例。responseBodyConverter 方法返回 MoshiResponseBodyConverter 实例,用于将响应体转换为 Java 对象;requestBodyConverter 方法返回 MoshiRequestBodyConverter 实例,用于将 Java 对象转换为请求体。

3.3.2 MoshiResponseBodyConverter 类

MoshiResponseBodyConverter 类实现了 Converter<ResponseBody, T> 接口,其 convert 方法使用 Moshi 的 JsonAdapter 从 ResponseBody 中读取 JSON 数据并转换为指定类型的 Java 对象。

3.3.3 MoshiRequestBodyConverter 类

MoshiRequestBodyConverter 类实现了 Converter<T, RequestBody> 接口,其 convert 方法使用 Moshi 的 JsonAdapter 将 Java 对象转换为 JSON 数据,并创建 RequestBody 对象。

四、数据转换模块的工作流程

4.1 创建 Retrofit 实例时添加转换器工厂

java

// 创建 Retrofit 实例时添加 GsonConverterFactory
Retrofit retrofit = new Retrofit.Builder().baseUrl("https://api.example.com/").addConverterFactory(GsonConverterFactory.create()).build();

在创建 Retrofit 实例时,通过 addConverterFactory 方法添加转换器工厂,这些工厂会被添加到 Retrofit 类的 converterFactories 列表中。

4.2 接口方法调用时创建转换器

java

// 定义 API 接口
public interface ApiService {@GET("users/{id}")Call<User> getUser(@Path("id") int id);
}// 创建 API 服务实例
ApiService apiService = retrofit.create(ApiService.class);
Call<User> call = apiService.getUser(1);

当调用 API 接口方法时,Retrofit 会根据方法的返回类型和参数类型,调用 createResponseConverter 和 createRequestBodyConverter 方法,遍历 converterFactories 列表,查找合适的转换器工厂并创建转换器。

4.3 请求体转换

java

// 在 OkHttpCall 类中进行请求体转换
final class OkHttpCall<T> implements Call<T> {private final ServiceMethod<T, ?> serviceMethod;private final Object[] args;OkHttpCall(ServiceMethod<T, ?> serviceMethod, Object[] args) {this.serviceMethod = serviceMethod;this.args = args;}@Overridepublic Request request() {// 创建请求体RequestBody body = serviceMethod.toRequestBody(args);// 创建 OkHttp 的 Request 对象return new Request.Builder().url(serviceMethod.requestFactory.url(args)).headers(serviceMethod.requestFactory.headers(args)).method(serviceMethod.httpMethod, body).build();}
}// 在 ServiceMethod 类中调用请求体转换器
abstract class ServiceMethod<T, R> {final RequestFactory requestFactory;final Converter<?, RequestBody> requestBodyConverter;ServiceMethod(Builder<T, R> builder) {this.requestFactory = builder.requestFactory;this.requestBodyConverter = builder.requestBodyConverter;}RequestBody toRequestBody(Object[] args) {Object value = args[requestFactory.parameterHandlers.length - 1];try {// 调用请求体转换器进行转换return requestBodyConverter.convert(value);} catch (IOException e) {throw new RuntimeException("Unable to convert request body", e);}}
}

在 OkHttpCall 类的 request 方法中,调用 ServiceMethod 的 toRequestBody 方法,该方法会调用请求体转换器的 convert 方法,将请求参数转换为 RequestBody 对象。

4.4 响应体转换

java

// 在 OkHttpCall 类中进行响应体转换
final class OkHttpCall<T> implements Call<T> {@Overridepublic Response<T> execute() throws IOException {okhttp3.Call call = rawCall();okhttp3.Response rawResponse = call.execute();try {// 解析响应体return parseResponse(rawResponse);} catch (Throwable t) {try {rawResponse.body().close();} catch (IOException ignored) {}throw t;}}private Response<T> parseResponse(okhttp3.Response rawResponse) throws IOException {ResponseBody rawBody = rawResponse.body();rawResponse = rawResponse.newBuilder().body(new NoContentResponseBody(rawBody.contentType(), rawBody.contentLength())).build();int code = rawResponse.code();if (code < 200 || code >= 300) {try {// 处理错误响应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 {// 调用响应体转换器进行转换T body = serviceMethod.toResponse(catchingBody);return Response.success(body, rawResponse);} catch (RuntimeException e) {catchingBody.throwIfCaught();throw e;}}
}// 在 ServiceMethod 类中调用响应体转换器
abstract class ServiceMethod<T, R> {final Converter<ResponseBody, T> responseBodyConverter;ServiceMethod(Builder<T, R> builder) {this.responseBodyConverter = builder.responseBodyConverter;}T toResponse(ResponseBody body) throws IOException {// 调用响应体转换器进行转换return responseBodyConverter.convert(body);}
}

在 OkHttpCall 类的 execute 方法中,调用 parseResponse 方法,该方法会调用 ServiceMethod 的 toResponse 方法,该方法会调用响应体转换器的 convert 方法,将 ResponseBody 对象转换为 Java 对象。

五、自定义转换器工厂

5.1 自定义转换器接口

java

// 自定义转换器接口
public interface CustomConverter<F, T> {T convert(F value) throws IOException;
}// 自定义转换器工厂接口
public abstract class CustomConverterFactory extends Converter.Factory {public abstract <T> CustomConverter<ResponseBody, T> responseBodyConverter(Type type, Annotation[] annotations, Retrofit retrofit);public abstract <T> CustomConverter<T, RequestBody> requestBodyConverter(Type type, Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit);
}

首先定义自定义的转换器接口 CustomConverter 和转换器工厂接口 CustomConverterFactory

5.2 实现自定义转换器工厂

java

// 自定义转换器工厂实现
public class MyCustomConverterFactory extends CustomConverterFactory {@Overridepublic <T> CustomConverter<ResponseBody, T> responseBodyConverter(Type type, Annotation[] annotations, Retrofit retrofit) {return new MyCustomResponseBodyConverter<>();}@Overridepublic <T> CustomConverter<T, RequestBody> requestBodyConverter(Type type, Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) {return new MyCustomRequestBodyConverter<>();}
}// 自定义响应体转换器
class MyCustomResponseBodyConverter<T> implements CustomConverter<ResponseBody, T> {@Overridepublic T convert(ResponseBody value) throws IOException {// 实现自定义的响应体转换逻辑// 这里只是简单示例,实际中需要根据具体需求实现return null;}
}// 自定义请求体转换器
class MyCustomRequestBodyConverter<T> implements CustomConverter<T, RequestBody> {@Overridepublic RequestBody convert(T value) throws IOException {// 实现自定义的请求体转换逻辑// 这里只是简单示例,实际中需要根据具体需求实现return null;}
}

实现自定义的转换器工厂 MyCustomConverterFactory,并实现 responseBodyConverter 和 requestBodyConverter 方法,返回自定义的响应体转换器和请求体转换器。

5.3 使用自定义转换器工厂

java

// 创建 Retrofit 实例时添加自定义转换器工厂
Retrofit retrofit = new Retrofit.Builder().baseUrl("https://api.example.com/").addConverterFactory(new MyCustomConverterFactory()).build();

在创建 Retrofit 实例时,

六、数据转换模块的异常处理

6.1 请求体转换异常

在请求体转换过程中,可能会因为各种原因抛出异常,比如数据格式错误、序列化失败等。以下是 ServiceMethod 类中请求体转换部分可能出现异常的源码分析:

java

abstract class ServiceMethod<T, R> {final RequestFactory requestFactory;final Converter<?, RequestBody> requestBodyConverter;ServiceMethod(Builder<T, R> builder) {this.requestFactory = builder.requestFactory;this.requestBodyConverter = builder.requestBodyConverter;}RequestBody toRequestBody(Object[] args) {Object value = args[requestFactory.parameterHandlers.length - 1];try {// 调用请求体转换器进行转换return requestBodyConverter.convert(value);} catch (IOException e) {// 捕获转换过程中可能出现的 IO 异常throw new RuntimeException("Unable to convert request body", e);}}
}

在 toRequestBody 方法中,调用 requestBodyConverter 的 convert 方法进行请求体转换。如果转换过程中抛出 IOException,会将其封装成 RuntimeException 抛出,以通知调用者请求体转换失败。

6.2 响应体转换异常

响应体转换过程同样可能出现异常,比如 JSON 解析错误、数据类型不匹配等。以下是 OkHttpCall 类中响应体转换部分的异常处理源码分析:

java

final class OkHttpCall<T> implements Call<T> {private Response<T> parseResponse(okhttp3.Response rawResponse) throws IOException {ResponseBody rawBody = rawResponse.body();rawResponse = rawResponse.newBuilder().body(new NoContentResponseBody(rawBody.contentType(), rawBody.contentLength())).build();int code = rawResponse.code();if (code < 200 || code >= 300) {try {// 处理错误响应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 {// 调用响应体转换器进行转换T body = serviceMethod.toResponse(catchingBody);return Response.success(body, rawResponse);} catch (RuntimeException e) {// 捕获转换过程中可能出现的运行时异常catchingBody.throwIfCaught();throw e;}}
}abstract class ServiceMethod<T, R> {final Converter<ResponseBody, T> responseBodyConverter;ServiceMethod(Builder<T, R> builder) {this.responseBodyConverter = builder.responseBodyConverter;}T toResponse(ResponseBody body) throws IOException {// 调用响应体转换器进行转换return responseBodyConverter.convert(body);}
}

在 parseResponse 方法中,调用 serviceMethod 的 toResponse 方法进行响应体转换。如果转换过程中抛出 RuntimeException,会先调用 catchingBody.throwIfCaught() 检查是否有捕获到的异常,然后再将异常抛出,以通知调用者响应体转换失败。

6.3 转换器工厂创建转换器异常

在 Retrofit 类的 createResponseConverter 和 createRequestBodyConverter 方法中,遍历 converterFactories 列表创建转换器时,也可能会抛出异常。以下是相关源码分析:

java

public final class Retrofit {// 创建响应转换器private static <T> Converter<ResponseBody, T> createResponseConverter(Retrofit retrofit, Method method, Type responseType) {Annotation[] annotations = method.getAnnotations();try {// 遍历转换器工厂列表,查找合适的转换器工厂for (Converter.Factory factory : retrofit.converterFactories()) {// 调用工厂的 responseBodyConverter 方法创建响应体转换器Converter<ResponseBody, ?> converter = factory.responseBodyConverter(responseType, annotations, retrofit);if (converter != null) {// 找到合适的转换器,返回return (Converter<ResponseBody, T>) converter;}}} catch (RuntimeException e) {// 捕获创建转换器过程中可能出现的运行时异常throw methodError(method, e, "Unable to create converter for %s", responseType);}throw methodError(method, "Could not locate response converter for %s.", responseType);}// 创建请求体转换器private static <T> Converter<T, RequestBody> createRequestBodyConverter(Retrofit retrofit, Method method, Type requestType, Annotation[] parameterAnnotations) {Annotation[] methodAnnotations = method.getAnnotations();try {// 遍历转换器工厂列表,查找合适的转换器工厂for (Converter.Factory factory : retrofit.converterFactories()) {// 调用工厂的 requestBodyConverter 方法创建请求体转换器Converter<?, RequestBody> converter = factory.requestBodyConverter(requestType, parameterAnnotations, methodAnnotations, retrofit);if (converter != null) {// 找到合适的转换器,返回return (Converter<T, RequestBody>) converter;}}} catch (RuntimeException e) {// 捕获创建转换器过程中可能出现的运行时异常throw methodError(method, e, "Unable to create converter for %s", requestType);}throw methodError(method, "Could not locate request body converter for %s.", requestType);}
}

在 createResponseConverter 和 createRequestBodyConverter 方法中,调用工厂的 responseBodyConverter 或 requestBodyConverter 方法创建转换器时,如果抛出 RuntimeException,会将其封装成 methodError 异常抛出,以通知调用者创建转换器失败。

七、数据转换模块的性能优化

7.1 缓存转换器

在 Retrofit 中,每次调用接口方法时都会尝试创建转换器,这可能会带来一定的性能开销。可以通过缓存已经创建的转换器来避免重复创建。以下是一个简单的缓存实现示例:

java

import java.lang.reflect.Type;
import java.util.HashMap;
import java.util.Map;public class ConverterCache {private static final Map<Type, Object> converterCache = new HashMap<>();public static <T> Converter<ResponseBody, T> getResponseConverter(Type type, Converter.Factory factory, Retrofit retrofit) {@SuppressWarnings("unchecked")Converter<ResponseBody, T> converter = (Converter<ResponseBody, T>) converterCache.get(type);if (converter == null) {converter = factory.responseBodyConverter(type, new Annotation[0], retrofit);if (converter != null) {converterCache.put(type, converter);}}return converter;}public static <T> Converter<T, RequestBody> getRequestConverter(Type type, Converter.Factory factory, Retrofit retrofit) {@SuppressWarnings("unchecked")Converter<T, RequestBody> converter = (Converter<T, RequestBody>) converterCache.get(type);if (converter == null) {converter = factory.requestBodyConverter(type, new Annotation[0], new Annotation[0], retrofit);if (converter != null) {converterCache.put(type, converter);}}return converter;}
}

在 Retrofit 中使用缓存:

java

public final class Retrofit {// 创建响应转换器private static <T> Converter<ResponseBody, T> createResponseConverter(Retrofit retrofit, Method method, Type responseType) {Annotation[] annotations = method.getAnnotations();for (Converter.Factory factory : retrofit.converterFactories()) {Converter<ResponseBody, T> converter = ConverterCache.getResponseConverter(responseType, factory, retrofit);if (converter != null) {return converter;}}throw methodError(method, "Could not locate response converter for %s.", responseType);}// 创建请求体转换器private static <T> Converter<T, RequestBody> createRequestBodyConverter(Retrofit retrofit, Method method, Type requestType, Annotation[] parameterAnnotations) {Annotation[] methodAnnotations = method.getAnnotations();for (Converter.Factory factory : retrofit.converterFactories()) {Converter<T, RequestBody> converter = ConverterCache.getRequestConverter(requestType, factory, retrofit);if (converter != null) {return converter;}}throw methodError(method, "Could not locate request body converter for %s.", requestType);}
}

通过缓存转换器,可以避免重复创建相同类型的转换器,提高性能。

7.2 选择合适的转换器

不同的转换器在性能上可能会有差异,例如 GsonConverterFactory 和 MoshiConverterFactory 都可以处理 JSON 数据,但 Moshi 在某些场景下可能会有更好的性能。在选择转换器时,需要根据具体的需求和数据特点进行选择。

7.3 减少不必要的转换

在某些情况下,可以避免进行不必要的数据转换。例如,如果服务器返回的数据可以直接使用,就不需要将其转换为 Java 对象再进行处理。可以通过自定义转换器来实现直接处理原始数据。

八、数据转换模块与其他模块的交互

8.1 与 CallAdapter 模块的交互

CallAdapter 模块负责将 Call 对象转换为其他类型,如 ObservableCompletable 等。数据转换模块和 CallAdapter 模块在请求和响应处理过程中相互协作。以下是一个简单的交互示例:

java

public interface ApiService {@GET("users/{id}")Observable<User> getUser(@Path("id") int id);
}Retrofit retrofit = new Retrofit.Builder().baseUrl("https://api.example.com/").addConverterFactory(GsonConverterFactory.create()).addCallAdapterFactory(RxJava2CallAdapterFactory.create()).build();ApiService apiService = retrofit.create(ApiService.class);
Observable<User> observable = apiService.getUser(1);

在这个示例中,GsonConverterFactory 负责将响应体转换为 User 对象,RxJava2CallAdapterFactory 负责将 Call 对象转换为 Observable 对象。

8.2 与 OkHttp 模块的交互

Retrofit 底层使用 OkHttp 进行网络请求,数据转换模块和 OkHttp 模块在请求体和响应体的处理上进行交互。OkHttp 负责发送请求和接收响应,数据转换模块负责将请求参数转换为 RequestBody 对象,将 ResponseBody 对象转换为 Java 对象。以下是相关源码分析:

java

final class OkHttpCall<T> implements Call<T> {@Overridepublic Request request() {// 创建请求体RequestBody body = serviceMethod.toRequestBody(args);// 创建 OkHttp 的 Request 对象return new Request.Builder().url(serviceMethod.requestFactory.url(args)).headers(serviceMethod.requestFactory.headers(args)).method(serviceMethod.httpMethod, body).build();}@Overridepublic Response<T> execute() throws IOException {okhttp3.Call call = rawCall();okhttp3.Response rawResponse = call.execute();try {// 解析响应体return parseResponse(rawResponse);} catch (Throwable t) {try {rawResponse.body().close();} catch (IOException ignored) {}throw t;}}
}

在 request 方法中,调用 serviceMethod 的 toRequestBody 方法将请求参数转换为 RequestBody 对象,然后创建 OkHttp 的 Request 对象。在 execute 方法中,调用 parseResponse 方法将 OkHttp 的 Response 对象中的 ResponseBody 转换为 Java 对象。

九、数据转换模块的未来发展趋势

9.1 支持更多的数据格式

随着技术的发展,可能会出现更多的数据格式,如 Protocol Buffers、Avro 等。Retrofit 的数据转换模块可能会支持更多的数据格式,以满足不同的需求。

9.2 更好的性能优化

未来的数据转换模块可能会进行更多的性能优化,如使用更高效的序列化和反序列化算法,减少内存开销和 CPU 占用。

9.3 与更多的框架集成

Retrofit 可能会与更多的框架进行集成,如 Kotlin 的协程、Flutter 等,以提供更好的开发体验。

9.4 增强的错误处理和调试功能

数据转换模块可能会提供更详细的错误信息和调试工具,帮助开发者更快地定位和解决问题。例如,在异常信息中提供更多的上下文信息,或者提供可视化的调试工具。

十、总结

Retrofit 的数据转换模块是一个非常重要的模块,它负责将请求参数序列化为 HTTP 请求体,以及将 HTTP 响应体反序列化为 Java 对象。通过对数据转换模块的源码分析,我们了解了其核心概念、常见的转换器工厂实现、工作流程、异常处理、性能优化、与其他模块的交互以及未来发展趋势。掌握这些知识可以帮助我们更好地使用和扩展 Retrofit 框架,提高开发效率和应用性能。在实际开发中,我们可以根据具体的需求选择合适的转换器工厂,进行自定义转换器的开发,以及对数据转换模块进行性能优化,以满足不同的业务需求。同时,我们也需要关注数据转换模块的未来发展趋势,以便及时跟上技术的发展步伐。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词