Impossible de créer un adaptateur d’appel pour l’exemple de classe.Simple

J’utilise retrofit 2.0.0-beta1 avec SimpleXml. Je veux récupérer une ressource Simple (XML) à partir d’un service REST. Marshalling / Unmarshalling L’object Simple avec SimpleXML fonctionne correctement.

En utilisant ce code (converti avant le code 2.0.0):

final Retrofit rest = new Retrofit.Builder() .addConverterFactory(SimpleXmlConverterFactory.create()) .baseUrl(endpoint) .build(); SimpleService service = rest.create(SimpleService.class); LOG.info(service.getSimple("572642")); 

Un service:

 public interface SimpleService { @GET("/simple/{id}") Simple getSimple(@Path("id") Ssortingng id); } 

Je reçois cette exception:

 Exception in thread "main" java.lang.IllegalArgumentException: Unable to create call adapter for class example.Simple for method SimpleService.getSimple at retrofit.Utils.methodError(Utils.java:201) at retrofit.MethodHandler.createCallAdapter(MethodHandler.java:51) at retrofit.MethodHandler.create(MethodHandler.java:30) at retrofit.Retrofit.loadMethodHandler(Retrofit.java:138) at retrofit.Retrofit$1.invoke(Retrofit.java:127) at com.sun.proxy.$Proxy0.getSimple(Unknown Source) 

Qu’est-ce que je rate? Je sais que le type de retour par un Call fonctionne. Mais je souhaite que le service renvoie des objects métier en tant que type (et en mode synchro).

METTRE À JOUR

Après avoir ajouté les dépendances supplémentaires et .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) comme suggéré par différentes réponses, je reçois toujours cette erreur:

 Caused by: java.lang.IllegalArgumentException: Could not locate call adapter for class simple.Simple. Tried: * retrofit.RxJavaCallAdapterFactory * retrofit.DefaultCallAdapter$1 

Réponse courte: retourne Call dans votre interface de service.

Il semble que Retrofit 2.0 essaie de trouver un moyen de créer l’object proxy pour votre interface de service. Il s’attend à ce que vous écriviez ceci:

 public interface SimpleService { @GET("/simple/{id}") Call getSimple(@Path("id") Ssortingng id); } 

Cependant, il souhaite toujours jouer de manière agréable et être flexible lorsque vous ne souhaitez pas renvoyer un Call . Pour supporter cela, il a le concept d’un CallAdapter , qui est censé savoir comment adapter un Call en un Simple .

L’utilisation de RxJavaCallAdapterFactory n’est utile que si vous essayez de renvoyer rx.Observable .

La solution la plus simple consiste à renvoyer un Call fonction des modifications apscopes. Vous pouvez également écrire un CallAdapter.Factory si vous en avez vraiment besoin.

append des dépendances:

 comstack 'com.squareup.retrofit:retrofit:2.0.0-beta1' comstack 'com.squareup.retrofit:adapter-rxjava:2.0.0-beta1' comstack 'com.squareup.retrofit:converter-gson:2.0.0-beta1' 

créez votre adaptateur de cette façon:

 Retrofit rest = new Retrofit.Builder() .baseUrl(endpoint) .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) .addConverterFactory(SimpleXmlConverterFactory.create()) .build(); 

addCallAdapterFactory () et addConverterFactory () doivent tous deux être appelés.

Un service:

 public interface SimpleService { @GET("/simple/{id}") Call getSimple(@Path("id") Ssortingng id); } 

Modifier Simple pour Call .

Avec le nouveau Retrofit (2. +), vous devez append addCallAdapterFactory, qui peut être normal ou RxJavaCallAdapterFactory (pour Observable). Je pense que vous pouvez append plus que les deux aussi. Il vérifie automatiquement lequel utiliser. Voir un exemple de travail ci-dessous. Vous pouvez également consulter ce lien pour plus de détails.

  Retrofit retrofit = new Retrofit.Builder().baseUrl(ApiConfig.BASE_URL) .addConverterFactory(GsonConverterFactory.create()) .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) .build() 

Ajoutez les dépendances suivantes pour la modernisation 2

  comstack 'com.squareup.retrofit2:retrofit:2.1.0' 

pour GSON

  comstack 'com.squareup.retrofit2:converter-gson:2.1.0' 

pour les observables

 comstack 'com.squareup.retrofit2:adapter-rxjava:2.1.0' 

Dans votre cas pour XML, vous devez inclure les dépendances suivantes

  comstack 'com.squareup.retrofit2:converter-simplexml:2.1.0' 

Mettre à jour l’appel de service comme ci-dessous

 final Retrofit rest = new Retrofit.Builder() .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) .addConverterFactory(SimpleXmlConverterFactory.create()) .baseUrl(endpoint) .build(); SimpleService service = rest.create(SimpleService.class); 

Si vous voulez utiliser retrofit2 et que vous ne voulez pas toujours retourner retrofit2.Call , vous devez créer votre propre CallAdapter.Factory qui renvoie un type simple comme prévu. Le code simple peut ressembler à ceci:

 import retrofit2.Call; import retrofit2.CallAdapter; import retrofit2.Retrofit; import java.lang.annotation.Annotation; import java.lang.reflect.Type; public class SynchronousCallAdapterFactory extends CallAdapter.Factory { public static CallAdapter.Factory create() { return new SynchronousCallAdapterFactory(); } @Override public CallAdapter get(final Type returnType, Annotation[] annotations, Retrofit retrofit) { // if returnType is retrofit2.Call, do nothing if (returnType.toSsortingng().contains("retrofit2.Call")) { return null; } return new CallAdapter() { @Override public Type responseType() { return returnType; } @Override public Object adapt(Call call) { try { return call.execute().body(); } catch (Exception e) { throw new RuntimeException(e); // do something better } } }; } } 

Ensuite, il suffit de vous inscrire dans SynchronousCallAdapterFactory dans Retrofit pour résoudre votre problème.

 Retrofit rest = new Retrofit.Builder() .baseUrl(endpoint) .addConverterFactory(SimpleXmlConverterFactory.create()) .addCallAdapterFactory(SynchronousCallAdapterFactory.create()) .build(); 

Après cela, vous pouvez retourner un type simple sans retrofit2.Call .

 public interface SimpleService { @GET("/simple/{id}") Simple getSimple(@Path("id") Ssortingng id); } 

dans mon cas en utilisant cette

 comstack 'com.jakewharton.retrofit:retrofit2-rxjava2-adapter:1.0.0' 

avec ça

 new Retrofit.Builder().addCallAdapterFactory(RxJava2CallAdapterFactory.create())... 

résolu le problème quand rien d’autre n’a fonctionné

Vous pouvez implémenter un rappel, obtenez la fonction Simple from onResponse.

 public class MainActivity extends Activity implements Callback { protected void onCreate(Bundle savedInstanceState) { final Retrofit rest = new Retrofit.Builder() .addConverterFactory(SimpleXmlConverterFactory.create()) .baseUrl(endpoint) .build(); SimpleService service = rest.create(SimpleService.class); Call call = service.getSimple("572642"); //asynchronous call call.enqueue(this); return true; } @Override public void onResponse(Response response, Retrofit retrofit) { // response.body() has the return object(s) } @Override public void onFailure(Throwable t) { // do something } } 

Simplement pour que les exemples d’appels soient plus clairs pour les personnes qui migrent, n’utilisent pas Rx ou qui souhaitent des appels synchrones – Call remplace essentiellement (wraps) Response, ce qui signifie:

 Response createRecord(...); 

devient

 Call createRecord(...); 

et pas

 Call> createRecord(...); 

(qui nécessitera toujours un adaptateur)


L’Appel vous permettra alors de continuer à utiliser isSuccessful car il renvoie réellement une réponse. Vous pouvez donc faire quelque chose comme:

 myApi.createRecord(...).execute().isSuccessful() 

Ou accédez à votre type (MyObject) comme:

 MyObject myObj = myApi.createRecord(...).execute().body(); 

La façon dont j’ai résolu ce problème consistait à append ceci au fichier de gradation de l’application. Si la configuration n’est pas définie, il y aura des conflits, peut-être que cela sera corrigé dans la version stable de la bibliothèque:

 configurations { comstack.exclude group: 'stax' comstack.exclude group: 'xpp3' } dependencies { comstack 'com.squareup.retrofit:retrofit:2.0.0-beta1' comstack 'com.squareup.retrofit:converter-simplexml:2.0.0-beta1' } 

et créez votre adaptateur de cette façon:

  Retrofit retrofit = new Retrofit.Builder() .baseUrl(endPoint) .addConverterFactory(SimpleXmlConverterFactory.create()) .build(); 

J’espère que cela aide!