J'utilise la retrofit 2.0.0-beta1 avec SimpleXml. Je veux récupérer une ressource simple (XML) à partir d'un service REST. Marshalling / Unmarshalling l'objet Simple avec SimpleXML fonctionne très bien.
Lors de l'utilisation de ce code (format 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") String id);
}
J'obtiens 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 envelopper le type de retour par un Call
fonctionne. Mais je souhaite que le service renvoie les objets métier sous forme de type (et fonctionne en mode synchro).
MISE À JOUR
Après avoir ajouté les dépendances supplémentaires et .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
comme suggéré par différentes réponses, j'obtiens toujours cette erreur:
Caused by: java.lang.IllegalArgumentException: Could not locate call adapter for class simple.Simple. Tried:
* retrofit.RxJavaCallAdapterFactory
* retrofit.DefaultCallAdapter$1
java
rest
retrofit
simple-framework
rmuller
la source
la source
Réponses:
Réponse courte: retournez
Call<Simple>
dans votre interface de service.Il semble que Retrofit 2.0 essaie de trouver un moyen de créer l'objet proxy pour votre interface de service. Il attend de vous que vous écriviez ceci:
public interface SimpleService { @GET("/simple/{id}") Call<Simple> getSimple(@Path("id") String id); }
Cependant, il veut toujours jouer gentiment et être flexible lorsque vous ne voulez pas retourner un fichier
Call
. Pour supporter cela, il a le concept de aCallAdapter
, qui est censé savoir comment adapter aCall<Simple>
en aSimple
.L'utilisation de
RxJavaCallAdapterFactory
n'est utile que si vous essayez de revenirrx.Observable<Simple>
.La solution la plus simple consiste à renvoyer un
Call
tel que prévu par Retrofit. Vous pouvez également écrire unCallAdapter.Factory
si vous en avez vraiment besoin.la source
Call<Simple>
c'est ainsi que cela fonctionne. Cependant, comme indiqué dans ma question, ma préférence est de simplement revenirSimple
(comme c'était le cas dans la version précédente). Ma conclusion est : pas possible sans code supplémentaire.Call<Simple>
est rompu. À quel paquetSimple
appartient-il?Simple
est la classe mentionnée dans la question du PO. Le lien est àCall<T>
.Dans le cas de Kotlin et des coroutines, cette situation s'est produite lorsque j'ai oublié de marquer la fonction de service api comme
suspend
lorsque j'appelle cette fonction depuisCoroutineScope(Dispatchers.IO).launch{}
:Usage:
val apiService = RetrofitFactory.makeRetrofitService() CoroutineScope(Dispatchers.IO).launch { val response = apiService.myGetRequest() // process response... }
ApiService.kt
interface ApiService { @GET("/my-get-request") suspend fun myGetRequest(): Response<String> }
la source
ajouter des dépendances:
compile 'com.squareup.retrofit:retrofit:2.0.0-beta1' compile 'com.squareup.retrofit:adapter-rxjava:2.0.0-beta1' compile '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 lesaddConverterFactory ()
deux doivent être appelés.Un service:
public interface SimpleService { @GET("/simple/{id}") Call<Simple> getSimple(@Path("id") String id); }
Modifiez
Simple
enCall<Simple>
.la source
Call
dans l'interface de serviceCompletableFuture
Voir stackoverflow.com/questions/32269064/…Avec le nouveau Retrofit (2. +), vous devez ajouter addCallAdapterFactory qui peut être normal ou RxJavaCallAdapterFactory (pour Observables). Je pense que vous pouvez ajouter plus que les deux. 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()
la source
compile 'com.squareup.retrofit:adapter-rxjava:2.0.0-beta1'
com.squareup.retrofit2:adapter-rxjava:2.1.0
etcom.squareup.retrofit2:converter-gson:2.1.0
Si vous voulez utiliser
retrofit2
et que vous ne voulez pas toujours revenirretrofit2.Call<T>
, vous devez créer le vôtreCallAdapter.Factory
qui retourne le 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<Object, Object> get(final Type returnType, Annotation[] annotations, Retrofit retrofit) { // if returnType is retrofit2.Call, do nothing if (returnType.toString().contains("retrofit2.Call")) { return null; } return new CallAdapter<Object, Object>() { @Override public Type responseType() { return returnType; } @Override public Object adapt(Call<Object> call) { try { return call.execute().body(); } catch (Exception e) { throw new RuntimeException(e); // do something better } } }; } }
Ensuite, enregistrez simplement le
SynchronousCallAdapterFactory
dans Retrofit devrait 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") String id); }
la source
2.0.0-beta3
c'était une interface, maintenant dans la version2.1.0
c'est une classe. J'ai édité mon code, pour être plus actuel. Merci.Simple getSimple()
et de cesResponse<Simple> getSimple()
requêtes: github.com/jaredsburrows/retrofit2-synchronous-adapter .Ajoutez les dépendances suivantes pour la modernisation 2
compile 'com.squareup.retrofit2:retrofit:2.1.0'
pour GSON
compile 'com.squareup.retrofit2:converter-gson:2.1.0'
pour les observables
compile 'com.squareup.retrofit2:adapter-rxjava:2.1.0'
Dans votre cas pour XML, vous devrez inclure les dépendances suivantes
compile 'com.squareup.retrofit2:converter-simplexml:2.1.0'
Mettez à 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);
la source
dans mon cas en utilisant ceci
compile 'com.jakewharton.retrofit:retrofit2-rxjava2-adapter:1.0.0'
avec ça
new Retrofit.Builder().addCallAdapterFactory(RxJava2CallAdapterFactory.create())...
a résolu le problème alors que rien d'autre ne fonctionnait
la source
Si vous n'utilisez pas RxJava, cela n'a aucun sens d'ajouter RxJava juste pour la modernisation.
2.5.0
a un support pourCompletableFuture
intégré que vous pouvez utiliser sans ajouter aucune autre bibliothèque ou adaptateur.build.gradle.kts
implementation("com.squareup.retrofit2:retrofit:2.5.0") implementation("com.squareup.retrofit2:retrofit-converters:2.5.0")
Api.kt
interface Api { @GET("/resource") fun listCompanies(): CompletableFuture<ResourceDto> }
Usage:
Retrofit.Builder() .addConverterFactory(SimpleXmlConverterFactory.create()) .baseUrl("https://api.example.com") .build() .create(Api::class.java)
la source
IllegalArgumentException: impossible de créer un adaptateur d'appel pour la classe java.lang.Object
Réponse courte: je l'ai résolu par les changements suivants
ext.retrofit2Version = '2.4.0' -> '2.6.0' implementation"com.squareup.retrofit2:retrofit:$retrofit2Version" implementation "com.squareup.retrofit2:adapter-rxjava2:$retrofit2Version" implementation "com.squareup.retrofit2:converter-gson:$retrofit2Version"
Bonne chance
la source
Juste pour rendre les exemples d'appel plus clairs pour les personnes qui migrent, n'utilisent pas Rx ou qui veulent des appels synchrones - L'appel remplace essentiellement (encapsule) la réponse, ce qui signifie:
Response<MyObject> createRecord(...);
devient
Call<MyObject> createRecord(...);
et pas
(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:Ou accédez à votre type (MyObject) comme:
la source
public interface SimpleService { @GET("/simple/{id}") Simple getSimple(@Path("id") String id); }
La communication avec le réseau se fait avec le thread séparé, vous devez donc changer votre Simple avec cela.
public interface SimpleService { @GET("/simple/{id}") Call<Simple> getSimple(@Path("id") String id); }
la source
Dans mon cas, j'ai utilisé
com.squareup.retrofit2:adapter-rxjava:2.5.0 //notice rxjava
au lieu de
com.squareup.retrofit2:adapter-rxjava2:2.5.0 //notice rxjava2
vous devriez utiliser
com.squareup.retrofit2:adapter-rxjava2:2.5.0
lors de l'utilisationio.reactivex.rxjava2
la source
Vous pouvez implémenter un rappel, obtenir la fonction Simple de onResponse.
public class MainActivity extends Activity implements Callback<Simple> { protected void onCreate(Bundle savedInstanceState) { final Retrofit rest = new Retrofit.Builder() .addConverterFactory(SimpleXmlConverterFactory.create()) .baseUrl(endpoint) .build(); SimpleService service = rest.create(SimpleService.class); Call<Simple> call = service.getSimple("572642"); //asynchronous call call.enqueue(this); return true; } @Override public void onResponse(Response<Simple> response, Retrofit retrofit) { // response.body() has the return object(s) } @Override public void onFailure(Throwable t) { // do something } }
la source
La façon dont j'ai résolu ce problème a été d'ajouter ceci au fichier gradle 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 { compile.exclude group: 'stax' compile.exclude group: 'xpp3' } dependencies { compile 'com.squareup.retrofit:retrofit:2.0.0-beta1' compile '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!
la source