如何制作自定义 Retrofit ConverterFactory 以将 ReponseBody 转换为新的 ResponseBody?
How make a custom Retrofit ConverterFactory to transform ReponseBody to a new ResponseBody?
我想将 "windows-1252" 中编码的服务的答案转换为 "unicode"。我正在尝试在改造中使用自定义转换器工厂来完成这项工作。我的自定义转换器尝试拦截 ResponseBody class,更改字符编码,并 return 一个新的 ResponseBody 进行改造以进行处理。
但它没有用。显然,内置转换器的改造首先拦截 ResponseBody class 并且无法再次处理。
有什么办法可以避免这种行为吗?
注意:当我有响应时,我可以使用映射函数来获取它,但我想在改造中学习如何做。
这是我的代码。
AnsiconverterFactory.java
-------------------------
public class AnsiConverterFactory extends Converter.Factory {
public static AnsiConverterFactory create() {
return new AnsiConverterFactory();
}
private AnsiConverterFactory() {
}
@Override
public @Nullable Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations, Retrofit retrofit) {
if (type == ResponseBody.class) {
return AnsiResponseBodyConverter.INSTANCE;
}
return null;
}
@Override
public Converter<?, String> stringConverter(Type type, Annotation[] annotations, Retrofit retrofit) {
return super.stringConverter(type, annotations, retrofit);
}
@Override
public Converter<?, RequestBody> requestBodyConverter(Type type, Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) {
return null;
}
}
AnsiResponseBodyConverter.java
------------------------------
public class AnsiResponseBodyConverter implements Converter<ResponseBody, ResponseBody> {
static final AnsiResponseBodyConverter INSTANCE = new AnsiResponseBodyConverter();
@Override
public ResponseBody convert(ResponseBody value) throws IOException {
Log.d("CONVERTER", " En convert de responsebodyconverter");
final CharBuffer todo = Charset.forName("windows-1252").decode(ByteBuffer.wrap(value.bytes()));
return ResponseBody.create(value.contentType(), todo.toString());
}
}
以及应用中的使用:
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://...some webservice here")
.addConverterFactory(BitmapConverterFactory.create())
.addConverterFactory(AnsiConverterFactory.create())
.client(clientBuilder.build())
.addCallAdapterFactory(RxJava3CallAdapterFactory.create())
.build();
终于在okhttp中使用拦截器解决了问题。这是代码:
class LoggingInterceptor implements Interceptor {
@Override
public Response intercept(Chain chain) throws IOException {
Response response = chain.proceed(chain.request());
ResponseBody body = response.body();
if (body.contentType().equals(MediaType.parse("text/csv"))) {
final CharBuffer todo = Charset.forName("windows-1252").decode(ByteBuffer.wrap(body.bytes()));
body = ResponseBody.create(body.contentType(), todo.toString());
Response.Builder builder = response.newBuilder();
return builder.headers(response.headers())
.body(body)
.build();
}
return response;
}
}
这是在 Retrofit 构建之前。
OkHttpClient.Builder clientBuilder = new OkHttpClient.Builder()
.addInterceptor(new LoggingInterceptor());
我想将 "windows-1252" 中编码的服务的答案转换为 "unicode"。我正在尝试在改造中使用自定义转换器工厂来完成这项工作。我的自定义转换器尝试拦截 ResponseBody class,更改字符编码,并 return 一个新的 ResponseBody 进行改造以进行处理。 但它没有用。显然,内置转换器的改造首先拦截 ResponseBody class 并且无法再次处理。 有什么办法可以避免这种行为吗?
注意:当我有响应时,我可以使用映射函数来获取它,但我想在改造中学习如何做。
这是我的代码。
AnsiconverterFactory.java
-------------------------
public class AnsiConverterFactory extends Converter.Factory {
public static AnsiConverterFactory create() {
return new AnsiConverterFactory();
}
private AnsiConverterFactory() {
}
@Override
public @Nullable Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations, Retrofit retrofit) {
if (type == ResponseBody.class) {
return AnsiResponseBodyConverter.INSTANCE;
}
return null;
}
@Override
public Converter<?, String> stringConverter(Type type, Annotation[] annotations, Retrofit retrofit) {
return super.stringConverter(type, annotations, retrofit);
}
@Override
public Converter<?, RequestBody> requestBodyConverter(Type type, Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) {
return null;
}
}
AnsiResponseBodyConverter.java
------------------------------
public class AnsiResponseBodyConverter implements Converter<ResponseBody, ResponseBody> {
static final AnsiResponseBodyConverter INSTANCE = new AnsiResponseBodyConverter();
@Override
public ResponseBody convert(ResponseBody value) throws IOException {
Log.d("CONVERTER", " En convert de responsebodyconverter");
final CharBuffer todo = Charset.forName("windows-1252").decode(ByteBuffer.wrap(value.bytes()));
return ResponseBody.create(value.contentType(), todo.toString());
}
}
以及应用中的使用:
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://...some webservice here")
.addConverterFactory(BitmapConverterFactory.create())
.addConverterFactory(AnsiConverterFactory.create())
.client(clientBuilder.build())
.addCallAdapterFactory(RxJava3CallAdapterFactory.create())
.build();
终于在okhttp中使用拦截器解决了问题。这是代码:
class LoggingInterceptor implements Interceptor {
@Override
public Response intercept(Chain chain) throws IOException {
Response response = chain.proceed(chain.request());
ResponseBody body = response.body();
if (body.contentType().equals(MediaType.parse("text/csv"))) {
final CharBuffer todo = Charset.forName("windows-1252").decode(ByteBuffer.wrap(body.bytes()));
body = ResponseBody.create(body.contentType(), todo.toString());
Response.Builder builder = response.newBuilder();
return builder.headers(response.headers())
.body(body)
.build();
}
return response;
}
}
这是在 Retrofit 构建之前。
OkHttpClient.Builder clientBuilder = new OkHttpClient.Builder()
.addInterceptor(new LoggingInterceptor());