Android改造2多个转换器(Gson & SimpleXML)错误

ohtdti5x  于 2022-11-06  发布在  Android
关注(0)|答案(3)|浏览(220)

在我的项目中(我正在使用Dagger 2,Retrofit 2 & OkHTTP,RxAndroid)我有2个不同的API调用。从一个我接收JSON,从其他- XML。我研究了this link,并添加了2个转换器,我需要我的Retrofit.Builder():

  1. @Provides
  2. @Singleton
  3. public Gson providesGson() {
  4. return new GsonBuilder().create();
  5. }
  6. @Provides
  7. @Singleton
  8. public Retrofit providesRetrofit(@NonNull OkHttpClient okHttpClient, @NonNull Gson gson) {
  9. return new Retrofit.Builder()
  10. .baseUrl(ConstantsManager.BASE_URL)
  11. .client(okHttpClient)
  12. .addConverterFactory(SimpleXmlConverterFactory.create())
  13. .addConverterFactory(GsonConverterFactory.create(gson))
  14. .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
  15. .build();
  16. }

但是,当我收到JSON(XML得到正确转换)时,我得到以下内容:

  1. D/OkHttp: {"date":"20.11.2016","bank":"PB","baseCurrency":980,"baseCurrencyLit":"UAH","exchangeRate":[{"baseCurrency":"UAH","currency":"AUD","saleRateNB":19.4452740,"purchaseRateNB":19.4452740},{"baseCurrency":"UAH","currency":"CAD","saleRateNB":19.4047320,"purchaseRateNB":19.4047320},{"baseCurrency":"UAH","currency":"CZK","saleRateNB":1.0322170,"purchaseRateNB":1.0322170,"saleRate":1.0800000,"purchaseRate":0.9800000},{"baseCurrency":"UAH","currency":"DKK","saleRateNB":3.7519280,"purchaseRateNB":3.7519280},{"baseCurrency":"UAH","currency":"HUF","saleRateNB":0.0902556,"purchaseRateNB":0.0902556},{"baseCurrency":"UAH","currency":"ILS","saleRateNB":6.7524710,"purchaseRateNB":6.7524710,"saleRate":7.0000000,"purchaseRate":6.3000000},{"baseCurrency":"UAH","currency":"JPY","saleRateNB":0.2384005,"purchaseRateNB":0.2384005,"saleRate":0.2500000,"purchaseRate":0.2200000},{"baseCurrency":"UAH","currency":"LVL","saleRateNB":0.2384005,"purchaseRateNB":0.2384005},{"baseCurrency":"UAH","currency":"LTL","saleRateNB":0.2384005,"purchaseRateNB":0.2384005},{"baseCurrency":"UAH","currency":"NOK","saleRateNB":3.0724120,"purchaseRateNB":3.0724120,"saleRate":3.2000000,"purchaseRate":2.9000000},{"baseCurrency":"UAH","currency":"SKK","saleRateNB":3.0724120,"purchaseRateNB":3.0724120},{"baseCurrency":"UAH","currency":"SEK","saleRateNB":2.8384710,"purchaseRateNB":2.8384710},{"baseCurrency":"UAH","currency":"CHF","saleRateNB":26.0049080,"purchaseRateNB":26.0049080,"saleRate":27.5000000,"purchaseRate":25.0000000},{"baseCurrency":"UAH","currency":"RUB","saleRateNB":0.4013400,"purchaseRateNB":0.4013400,"saleRate":0.4200000,"purchaseRate":0.4000000},{"baseCurrency":"UAH","currency":"GBP","saleRateNB":32.4460750,"purchaseRateNB":32.4460750,"saleRate":34.0000000,"purchaseRate":31.0000000},{"baseCurrency":"UAH","currency":"USD","saleRateNB":26.0534380,"purchaseRateNB":26.0534380,"saleRate":27.0000000,"purchaseRate":26.6000000},{"baseCurrency":"UAH","currency":"BYR","saleRateNB":26.0534380,"purchaseRateNB":26.0534380},{"baseCurrency":"UAH","currency":"EUR","saleRateNB":27.9214700,"purchaseRateNB":27.9214700,"saleRate":28.6000000,"purchaseRate":28.2000000},{"baseCurrency":"UAH","currency":"GEL","saleRateNB":10.5921530,"purchaseRateNB":10.5921530},{"baseCurrency":"UAH","currency":"PLZ","saleRateNB":6.2818280,"purchaseRateNB":6.2818280,"saleRate":6.6000000,"purchaseRate":5.9000000}]}
  2. D/OkHttp: <-- END HTTP (2377-byte body)
  3. E/DateCurrencyService: Error while loading data occurred!
  4. java.lang.RuntimeException: org.xmlpull.v1.XmlPullParserException: Unexpected token (position:TEXT {"date":"20.11.2...@1:2378 in java.io.InputStreamReader@2ec8965)
  5. at retrofit2.converter.simplexml.SimpleXmlResponseBodyConverter.convert(SimpleXmlResponseBodyConverter.java:44)
  6. at retrofit2.converter.simplexml.SimpleXmlResponseBodyConverter.convert(SimpleXmlResponseBodyConverter.java:23)
  7. at retrofit2.ServiceMethod.toResponse(ServiceMethod.java:117)
  8. at retrofit2.OkHttpCall.parseResponse(OkHttpCall.java:211)
  9. at retrofit2.OkHttpCall.execute(OkHttpCall.java:174)
  10. at retrofit2.adapter.rxjava.RxJavaCallAdapterFactory$RequestArbiter.request(RxJavaCallAdapterFactory.java:171)
  11. at rx.internal.operators.OperatorSubscribeOn$1$1$1.request(OperatorSubscribeOn.java:80)
  12. at rx.Subscriber.setProducer(Subscriber.java:209)
  13. at rx.Subscriber.setProducer(Subscriber.java:205)
  14. at rx.Subscriber.setProducer(Subscriber.java:205)
  15. at rx.internal.operators.OperatorSubscribeOn$1$1.setProducer(OperatorSubscribeOn.java:76)
  16. at rx.Subscriber.setProducer(Subscriber.java:205)
  17. at retrofit2.adapter.rxjava.RxJavaCallAdapterFactory$CallOnSubscribe.call(RxJavaCallAdapterFactory.java:152)
  18. at retrofit2.adapter.rxjava.RxJavaCallAdapterFactory$CallOnSubscribe.call(RxJavaCallAdapterFactory.java:138)
  19. at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:50)
  20. at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:30)
  21. at rx.Observable.unsafeSubscribe(Observable.java:8666)
  22. at rx.internal.operators.OperatorSubscribeOn$1.call(OperatorSubscribeOn.java:94)
  23. at rx.internal.schedulers.CachedThreadScheduler$EventLoopWorker$1.call(CachedThreadScheduler.java:220)
  24. at rx.internal.schedulers.ScheduledAction.run(ScheduledAction.java:55)
  25. at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:428)
  26. at java.util.concurrent.FutureTask.run(FutureTask.java:237)
  27. at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:272)
  28. at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1133)
  29. at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:607)
  30. at java.lang.Thread.run(Thread.java:761)
  31. Caused by: org.xmlpull.v1.XmlPullParserException: Unexpected token (position:TEXT {"date":"20.11.2...@1:2378 in java.io.InputStreamReader@2ec8965)
  32. at org.kxml2.io.KXmlParser.next(KXmlParser.java:432)
  33. at org.kxml2.io.KXmlParser.next(KXmlParser.java:313)
  34. at org.simpleframework.xml.stream.PullReader.read(PullReader.java:105)
  35. at org.simpleframework.xml.stream.PullReader.next(PullReader.java:89)
  36. at org.simpleframework.xml.stream.NodeReader.readElement(NodeReader.java:111)
  37. at org.simpleframework.xml.stream.NodeReader.readRoot(NodeReader.java:85)
  38. at org.simpleframework.xml.stream.NodeBuilder.read(NodeBuilder.java:84)
  39. at org.simpleframework.xml.stream.NodeBuilder.read(NodeBuilder.java:71)
  40. at org.simpleframework.xml.core.Persister.read(Persister.java:562)
  41. at retrofit2.converter.simplexml.SimpleXmlResponseBodyConverter.convert(SimpleXmlResponseBodyConverter.java:36)
  42. at retrofit2.converter.simplexml.SimpleXmlResponseBodyConverter.convert(SimpleXmlResponseBodyConverter.java:23) 
  43. at retrofit2.ServiceMethod.toResponse(ServiceMethod.java:117) 
  44. at retrofit2.OkHttpCall.parseResponse(OkHttpCall.java:211) 
  45. at retrofit2.OkHttpCall.execute(OkHttpCall.java:174) 
  46. at retrofit2.adapter.rxjava.RxJavaCallAdapterFactory$RequestArbiter.request(RxJavaCallAdapterFactory.java:171) 
  47. at rx.internal.operators.OperatorSubscribeOn$1$1$1.request(OperatorSubscribeOn.java:80) 
  48. at rx.Subscriber.setProducer(Subscriber.java:209) 
  49. at rx.Subscriber.setProducer(Subscriber.java:205) 
  50. at rx.Subscriber.setProducer(Subscriber.java:205) 
  51. at rx.internal.operators.OperatorSubscribeOn$1$1.setProducer(OperatorSubscribeOn.java:76) 
  52. at rx.Subscriber.setProducer(Subscriber.java:205) 
  53. at retrofit2.adapter.rxjava.RxJavaCallAdapterFactory$CallOnSubscribe.call(RxJavaCallAdapterFactory.java:152) 
  54. at retrofit2.adapter.rxjava.RxJavaCallAdapterFactory$CallOnSubscribe.call(RxJavaCallAdapterFactory.java:138) 
  55. at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:50) 
  56. at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:30) 
  57. at rx.Observable.unsafeSubscribe(Observable.java:8666) 
  58. at rx.internal.operators.OperatorSubscribeOn$1.call(OperatorSubscribeOn.java:94) 
  59. at rx.internal.schedulers.CachedThreadScheduler$EventLoopWorker$1.call(CachedThreadScheduler.java:220) 
  60. at rx.internal.schedulers.ScheduledAction.run(ScheduledAction.java:55) 
  61. at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:428) 
  62. at java.util.concurrent.FutureTask.run(FutureTask.java:237) 
  63. at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:272) 
  64. at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1133) 
  65. at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:607) 
  66. at java.lang.Thread.run(Thread.java:761) 

根据我的理解,SimpleXMLConverter会尝试转换我从第二次调用中获得的JSON响应(如前所述,来自第一次调用的XML响应会得到正确的转换)。我需要做的是用适当的转换器转换每个响应(用SimpleXMLConverter转换XML响应,用GsonConverter转换JSON响应)。
如果我试图切换添加转换器的顺序,在接收XML时会出现类似的错误(因为Gson转换器显然试图转换XML响应):

  1. D/OkHttp: <exchangerate><exchangerate ccy="EUR" ccy_name_ru="Евро " ccy_name_ua="Євро " ccy_name_en="Euro " base_ccy="UA" buy="27247312" unit="100.00000" date="2016.11.29" /><exchangerate ccy="RUR" ccy_name_ru="Российский рубль " ccy_name_ua="Росiйський рубль " ccy_name_en="Russian Rouble " base_ccy="UA" buy="39810" unit="10.00000" date="2016.11.29" /><exchangerate ccy="USD" ccy_name_ru="Доллар США " ccy_name_ua="Долар США " ccy_name_en="US Dollar " base_ccy="UA" buy="25724426" unit="100.00000" date="2016.11.29" /></exchangerate>
  2. D/OkHttp: <-- END HTTP (799-byte body)
  3. E/SyncService: Error while loading data occurred!
  4. com.google.gson.stream.MalformedJsonException: Use JsonReader.setLenient(true) to accept malformed JSON at line 1 column 1 path $
  5. at com.google.gson.stream.JsonReader.syntaxError(JsonReader.java:1559)
  6. at com.google.gson.stream.JsonReader.checkLenient(JsonReader.java:1401)
  7. at com.google.gson.stream.JsonReader.doPeek(JsonReader.java:593)
  8. at com.google.gson.stream.JsonReader.peek(JsonReader.java:425)
  9. at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:205)
  10. at retrofit2.converter.gson.GsonResponseBodyConverter.convert(GsonResponseBodyConverter.java:37)
  11. at retrofit2.converter.gson.GsonResponseBodyConverter.convert(GsonResponseBodyConverter.java:25)
  12. at retrofit2.ServiceMethod.toResponse(ServiceMethod.java:117)
  13. at retrofit2.OkHttpCall.parseResponse(OkHttpCall.java:211)
  14. at retrofit2.OkHttpCall.execute(OkHttpCall.java:174)
  15. at retrofit2.adapter.rxjava.RxJavaCallAdapterFactory$RequestArbiter.request(RxJavaCallAdapterFactory.java:171)
  16. at rx.internal.operators.OperatorSubscribeOn$1$1$1.request(OperatorSubscribeOn.java:80)
  17. at rx.Subscriber.setProducer(Subscriber.java:209)
  18. at rx.Subscriber.setProducer(Subscriber.java:205)
  19. at rx.Subscriber.setProducer(Subscriber.java:205)
  20. at rx.internal.operators.OperatorSubscribeOn$1$1.setProducer(OperatorSubscribeOn.java:76)
  21. at rx.Subscriber.setProducer(Subscriber.java:205)
  22. at retrofit2.adapter.rxjava.RxJavaCallAdapterFactory$CallOnSubscribe.call(RxJavaCallAdapterFactory.java:152)
  23. at retrofit2.adapter.rxjava.RxJavaCallAdapterFactory$CallOnSubscribe.call(RxJavaCallAdapterFactory.java:138)
  24. at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:50)
  25. at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:30)
  26. at rx.Observable.unsafeSubscribe(Observable.java:8666)
  27. at rx.internal.operators.OperatorSubscribeOn$1.call(OperatorSubscribeOn.java:94)
  28. at rx.internal.schedulers.CachedThreadScheduler$EventLoopWorker$1.call(CachedThreadScheduler.java:220)
  29. at rx.internal.schedulers.ScheduledAction.run(ScheduledAction.java:55)
  30. at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:428)
  31. at java.util.concurrent.FutureTask.run(FutureTask.java:237)
  32. at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:272)
  33. at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1133)
  34. at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:607)
  35. at java.lang.Thread.run(Thread.java:761)

如何使每个转换器转换相应的响应?
**UPD:**按照Marcin Jedynak的建议,我执行了以下操作:

1)添加了自定义Converter类:

  1. public class RetrofitUniversalConverter extends Converter.Factory {
  2. private final Converter.Factory xml;
  3. private final Converter.Factory json;
  4. @Inject
  5. public RetrofitUniversalConverter(@NonNull Gson gson) {
  6. xml = SimpleXmlConverterFactory.create();
  7. json = GsonConverterFactory.create(gson);
  8. }
  9. @Override
  10. public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations, Retrofit retrofit) {
  11. for (Annotation annotation : annotations) {
  12. if (annotation.getClass() == Xml.class) {
  13. return xml.responseBodyConverter(type, annotations, retrofit);
  14. }
  15. if (annotation.getClass() == Json.class) {
  16. return json.responseBodyConverter(type, annotations, retrofit);
  17. }
  18. }
  19. return null;
  20. }
  21. }

2)重写了我的Retrofit模块:

  1. @Provides
  2. @Singleton
  3. public Gson providesGson() {
  4. return new GsonBuilder().create();
  5. }
  6. @Provides
  7. @Singleton
  8. public Retrofit providesRetrofit(@NonNull OkHttpClient okHttpClient,
  9. @NonNull RetrofitUniversalConverter converter) {
  10. return new Retrofit.Builder()
  11. .baseUrl(ConstantsManager.BASE_URL)
  12. .client(okHttpClient)
  13. .addConverterFactory(converter)
  14. .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
  15. .build();
  16. }

3)然后,我在API接口中添加了注解:

  1. public interface PrivatbankApi {
  2. @GET @Xml
  3. Observable<CurrentRates> loadCurrentRates(@NonNull @Url String url);
  4. @GET("exchange_rates") @Json
  5. Observable<DateRates> loadDateRates(@NonNull @Query("json") Boolean json, @NonNull @Query("date") String date);
  6. }

但是我遇到了一个例外:

  1. E/AndroidRuntime: FATAL EXCEPTION: main
  2. Process: com.vedmedenko.exchangerates, PID: 5432
  3. java.lang.RuntimeException: Unable to start service com.vedmedenko.exchangerates.core.services.SyncService@68cf714 with Intent { flg=0x4 cmp=com.vedmedenko.exchangerates/.core.services.SyncService (has extras) }: java.lang.IllegalArgumentException: Unable to create converter for class com.vedmedenko.exchangerates.core.rest.models.current.CurrentRates
  4. for method PrivatbankApi.loadCurrentRates
  5. at android.app.ActivityThread.handleServiceArgs(ActivityThread.java:3343)
  6. at android.app.ActivityThread.-wrap21(ActivityThread.java)
  7. at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1582)
  8. at android.os.Handler.dispatchMessage(Handler.java:102)
  9. at android.os.Looper.loop(Looper.java:154)
  10. at android.app.ActivityThread.main(ActivityThread.java:6119)
  11. at java.lang.reflect.Method.invoke(Native Method)
  12. at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:886)
  13. at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:776)
  14. Caused by: java.lang.IllegalArgumentException: Unable to create converter for class com.vedmedenko.exchangerates.core.rest.models.current.CurrentRates
  15. for method PrivatbankApi.loadCurrentRates
  16. at retrofit2.ServiceMethod$Builder.methodError(ServiceMethod.java:720)
  17. at retrofit2.ServiceMethod$Builder.createResponseConverter(ServiceMethod.java:706)
  18. at retrofit2.ServiceMethod$Builder.build(ServiceMethod.java:167)
  19. at retrofit2.Retrofit.loadServiceMethod(Retrofit.java:166)
  20. at retrofit2.Retrofit$1.invoke(Retrofit.java:145)
  21. at java.lang.reflect.Proxy.invoke(Proxy.java:813)
  22. at $Proxy0.loadCurrentRates(Unknown Source)
  23. at com.vedmedenko.exchangerates.core.DataManager.loadCurrentRates(DataManager.java:29)
  24. at com.vedmedenko.exchangerates.core.services.SyncService.onStartCommand(SyncService.java:81)
  25. at android.app.ActivityThread.handleServiceArgs(ActivityThread.java:3326)
  26. ... 8 more
  27. Caused by: java.lang.IllegalArgumentException: Could not locate ResponseBody converter for class com.vedmedenko.exchangerates.core.rest.models.current.CurrentRates.
  28. Tried:
  29. * retrofit2.BuiltInConverters
  30. * com.vedmedenko.exchangerates.core.rest.converters.RetrofitUniversalConverter
  31. at retrofit2.Retrofit.nextResponseBodyConverter(Retrofit.java:346)
  32. at retrofit2.Retrofit.responseBodyConverter(Retrofit.java:308)
  33. at retrofit2.ServiceMethod$Builder.createResponseConverter(ServiceMethod.java:704)
  34. ... 16 more
vaj7vani

vaj7vani1#

检查Jake Wharton的this presentation,在那里他完全解决了你描述的问题(并提出了许多其他有用的技巧)。
简而言之,他建议创建表示您期望的数据格式的注解(例如,在您的例子中为JsonXml),并相应地注解您的API调用。然后定义您的自定义ConverterFactory,根据遇到的注解将其委托给GsonConverterFactorySimpleXmlConverterFactory
但是,您需要在Jake的解决方案中添加两项内容。
首先,不要忘记使用@Retention(RetentionPolicy.RUNTIME)对注解进行注解,否则在运行时不会保留这些注解:

  1. @Retention(RetentionPolicy.RUNTIME)
  2. public @interface Json {}

第二,在responseBodyConverter方法中接收到的注解实际上并不是您的注解,它们是系统创建的注解的代理。因此,您需要替换条件:

  1. annotation.getClass() == Json.class
  2. annotation.getClass() == Xml.class

与:

  1. annotation.annotationType() == Json.class
  2. annotation.annotationType() == Xml.class
展开查看全部
o2rvlv0m

o2rvlv0m2#

感谢@Marcin和推荐人。
下面是根据Marcin的注解(如果没有找到注解,则添加Json factory作为默认值)调整的Jake Warton所提演示文稿中的代码:

  1. public class AnnotatedConverterFactory extends Converter.Factory {
  2. @Retention(RetentionPolicy.RUNTIME)
  3. public @interface Json {}
  4. @Retention(RetentionPolicy.RUNTIME)
  5. public @interface Xml {}
  6. final Map<Class<?>, Converter.Factory> mFactoryMap;
  7. public AnnotatedConverterFactory(Map<Class<?>, Converter.Factory> factoryMap) {
  8. mFactoryMap = factoryMap;
  9. }
  10. @Override
  11. public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations, Retrofit retrofit) {
  12. for(Annotation annotation : annotations){
  13. Converter.Factory factory = mFactoryMap.get(annotation.annotationType());
  14. if(factory != null){
  15. return factory.responseBodyConverter(type, annotations, retrofit);
  16. }
  17. }
  18. //try to default to json in case no annotation on current method was found
  19. Converter.Factory jsonFactory = mFactoryMap.get(Json.class);
  20. if(jsonFactory != null){
  21. return jsonFactory.responseBodyConverter(type, annotations, retrofit);
  22. }
  23. return null;
  24. }
  25. static class Builder {
  26. Map<Class<?>, Converter.Factory> mFactoryMap = new LinkedHashMap<>();
  27. Builder add(Class<? extends Annotation> factoryType, Converter.Factory factory){
  28. if(factoryType == null) throw new NullPointerException("factoryType is null");
  29. if(factory == null) throw new NullPointerException("factory is null");
  30. mFactoryMap.put(factoryType, factory);
  31. return this;
  32. }
  33. public AnnotatedConverterFactory build(){
  34. return new AnnotatedConverterFactory(mFactoryMap);
  35. }
  36. }
  37. }

用法:

  1. interface RetrofitService{
  2. @POST
  3. @AnnotatedConverterFactory.Xml
  4. Call<Envelope> someApiMethodWithXmlRespoonse(@Url String url, @Body Envelope envelope);
  5. @POST
  6. @AnnotatedConverterFactory.Json
  7. Call<Envelope> someApiMethodWithJsonRespoonse(@Url String url, @Body Model model);
  8. }

示例化改造:

  1. Retrofit retrofit = new Retrofit.Builder()
  2. .baseUrl(BASE_URL)
  3. .client(mOkHttpClient)
  4. .addConverterFactory(new AnnotatedConverterFactory.Builder()
  5. .add(AnnotatedConverterFactory.Xml.class, SimpleXmlConverterFactory.createNonStrict())
  6. .add(AnnotatedConverterFactory.Json.class, GsonConverterFactory.create(mGson))
  7. .build()
  8. )
  9. mRetrofitService = retrofit.create(RetrofitService.class);
展开查看全部
nkkqxpd9

nkkqxpd93#

对于Kotlin用户来说,这要简单得多

  1. @MustBeDocumented
  2. @Target(
  3. AnnotationTarget.FUNCTION,
  4. AnnotationTarget.PROPERTY_GETTER,
  5. AnnotationTarget.PROPERTY_SETTER
  6. )
  7. @Retention(AnnotationRetention.RUNTIME)
  8. annotation class XmlResponse
  9. @MustBeDocumented
  10. @Target(
  11. AnnotationTarget.FUNCTION,
  12. AnnotationTarget.PROPERTY_GETTER,
  13. AnnotationTarget.PROPERTY_SETTER
  14. )
  15. @Retention(AnnotationRetention.RUNTIME)
  16. annotation class JsonResponse
  17. class MultipleConverterFactory(private val factories: Map<Class<*>, Converter.Factory>) : Converter.Factory() {
  18. override fun responseBodyConverter(
  19. type: Type,
  20. annotations: Array<Annotation>,
  21. retrofit: Retrofit
  22. ): Converter<ResponseBody, *>? {
  23. return annotations.mapNotNull { factories[it.annotationClass.javaObjectType] }
  24. .getOrNull(0)
  25. ?.responseBodyConverter(type, annotations, retrofit)
  26. }
  27. class Builder {
  28. private val factories = hashMapOf<Class<*>, Converter.Factory>()
  29. fun setXmlConverterFactory(converterFactory: Converter.Factory): Builder {
  30. factories[XmlResponse::class.java] = converterFactory
  31. return this
  32. }
  33. fun setJsonConverterFactory(converterFactory: Converter.Factory): Builder {
  34. factories[JsonResponse::class.java] = converterFactory
  35. return this
  36. }
  37. @Suppress("unused")
  38. fun addCustomConverterFactory(
  39. annotation: Class<out Annotation>,
  40. converterFactory: Converter.Factory
  41. ): Builder {
  42. factories[annotation] = converterFactory
  43. return this
  44. }
  45. fun build(): MultipleConverterFactory {
  46. return MultipleConverterFactory(factories)
  47. }
  48. }
  49. }

和用法

  1. Retrofit.Builder()
  2. // ...
  3. .addConverterFactory(
  4. MultipleConverterFactory.Builder()
  5. .setXmlConverterFactory(TikXmlConverterFactory.create(instance()))
  6. .setJsonConverterFactory(GsonConverterFactory.create(instance()))
  7. .build()
  8. )
  9. .build()
  10. // some API endpoint
  11. @XmlResponse
  12. @GET
  13. suspend fun getXml(
  14. @Url url: String
  15. ): MyModel
展开查看全部

相关问题