文章目錄
retrofit轉換工廠介紹
retrofit是個強大的工具,而retrofit converter可以把請求的結果轉爲可供我們直接使用的java bean對象。如果不使用轉換工廠retrofit則請求方法回只能爲ResponseBody對象。
官方爲我們提供了一些默認的轉換工廠:https://github.com/square/retrofit/tree/master/retrofit-converters
public interface GitHubService {
@GET("users/{user}")
Call<User> getUserInfo(@Path("user") String user);
}
要使用工廠就要在retrofit實例設置轉換工廠:
Retrofit retrofit = new Retrofit.Builder()
.addConverterFactory(GsonConverterFactory.create())
.build();
這裏設置了一個GsonConverterFactory,它可以把http請求響應json數據轉爲java bean;這裏json數據被反序列化爲User
對象了;但是這個retrofit對象就只能處理gson數據了;
一般服務器接口所返回的數據結構都是統一規範的,比如返回數據結構爲JSON;那如果有特殊情況怎麼辦?比如服務中有個接口返回xml數據,上面的retrofit實例就不能用了,只能從新創建了;
可以混用的轉換工廠CompositeConverterFactory
聲明工廠CompositeConverterFactory
自定義一個可以混用的轉換工廠,它自己並不處理數據,給它設置默認工廠來處理數據,比如GsonConverterFactory就處理json數據,設置SimpleXmlConverterFactory就處理xml數據;並且還可以在請求方法上設置註解
來動態設置轉換工廠;
CompositeConverterFactory.java
public class CompositeConverterFactory extends Converter.Factory {
private Converter.Factory mFactory;
public static CompositeConverterFactory create(Converter.Factory factory) {
if (factory == null) {
throw new NullPointerException("parameter is null");
} else {
return new CompositeConverterFactory(factory);
}
}
private CompositeConverterFactory(Converter.Factory factory) {
this.mFactory = factory;
}
@Override
public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations, Retrofit retrofit) {
Class<?> factoryClass = null;
for (Annotation annotation : annotations) {
if (annotation instanceof ResponseConverter) {
factoryClass = ((ResponseConverter) annotation).value();
break;
}
}
Converter.Factory factory = null;
if (factoryClass != null) {
try {
Method createMethod = factoryClass.getMethod("create");
factory = (Converter.Factory) createMethod.invoke(null);
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
if (factory == null && mFactory != null) {
factory = mFactory;
}
if (factory != null)
return factory.responseBodyConverter(type, annotations, retrofit);
return super.responseBodyConverter(type, annotations, retrofit);
}
@Override
public Converter<?, RequestBody> requestBodyConverter(Type type, Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) {
Class<?> factoryClass = null;
for (Annotation paramAnno : methodAnnotations) {
if (paramAnno instanceof RequestConverter) {
factoryClass = ((RequestConverter) paramAnno).value();
break;
}
}
Converter.Factory factory = null;
if (factoryClass != null) {
try {
Method createMethod = factoryClass.getMethod("create");
factory = (Converter.Factory) createMethod.invoke(null);
return factory.requestBodyConverter(type, parameterAnnotations, methodAnnotations, retrofit);
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
if (factory == null && mFactory != null) {
factory = mFactory;
}
if (factory != null)
return factory.requestBodyConverter(type, parameterAnnotations, methodAnnotations, retrofit);
return super.requestBodyConverter(type, parameterAnnotations, methodAnnotations, retrofit);
}
}
聲明註解@RequestConverter
@RequestConverter
@Documented
@Target({METHOD})
@Retention(RUNTIME)
public @interface RequestConverter {
Class<? extends Converter.Factory> value();
}
聲明註解@ResponseConverter
@ResponseConverter
@Documented
@Target({METHOD})
@Retention(RUNTIME)
public @interface ResponseConverter {
Class<? extends Converter.Factory> value();
}
CompositeConverterFactory的使用
使用自定義轉換工廠:
Retrofit retrofit = new Retrofit.Builder()
.addConverterFactory(CompositeConverterFactory.create(GsonConverterFactory.create()))
.build();
這裏默認設置GsonConverterFactory,默認處理json數據結構的數據。CompositeConverterFactory轉換什麼數據由傳入的默認工廠決定。
@RequestConverter @ResponseConverter 的使用:
CompositeConverterFactory.create(factory)
傳入參數爲默認工廠;
case1 接口返回的json數據轉爲對象
public interface GitHubService {
@ResponseConverter(GsonConverterFactory.class)
@GET("users/{user}")
Call<User> getUserInfo(@Path("user") String user);
}
case2 獲取接口返回的原始數據(字符串) json 或 xml 或 其他
@ResponseConverter(ScalarsConverterFactory.class)
@GET("users/{user}")
Call<String> getUserInfo2(@Path("user") String user);
case3 把javabean轉爲json字符串以post方式上傳到服務器端
@RequestConverter(GsonConverterFactory.class)
@POST("/uploaddata")
Call<String> upload(@Body User user);
是不是很簡單?It is easy!!!
在gradle中添加依賴即可使用
repositories {
jcenter()
}
dependencies {
implementation 'com.github.woodyhi.retrofit:composite-converter:0.1.3'
}
PS:源碼 https://github.com/woodyhi/retrofit-converter 其中有test代碼來演示。