Ich verwende Retrofit 2.0.0-Beta1 mit SimpleXml. Ich möchte eine einfache (XML) Ressource von einem REST-Service abrufen. Das Marshalling / Unmarshalling des Simple-Objekts mit SimpleXML funktioniert einwandfrei.
Bei Verwendung dieses Codes (konvertierter Code vor 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"));
Bedienung:
public interface SimpleService {
@GET("/simple/{id}")
Simple getSimple(@Path("id") String id);
}
Ich bekomme diese Ausnahme:
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)
Was vermisse ich? Ich weiß, dass das Umschließen des Rückgabetyps mit einem Call
funktioniert. Ich möchte jedoch, dass der Dienst Geschäftsobjekte als Typ zurückgibt (und im Synchronisierungsmodus arbeitet).
AKTUALISIEREN
Nach dem Hinzufügen der zusätzlichen Abhängigkeiten und .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
wie durch verschiedene Antworten vorgeschlagen, wird immer noch der folgende Fehler angezeigt:
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
Müller
quelle
quelle
Antworten:
Kurze Antwort: Rückkehr
Call<Simple>
in Ihre Serviceschnittstelle zurück.Es sieht so aus, als würde Retrofit 2.0 versuchen, das Proxy-Objekt für Ihre Serviceschnittstelle zu erstellen. Es erwartet, dass Sie dies schreiben:
public interface SimpleService { @GET("/simple/{id}") Call<Simple> getSimple(@Path("id") String id); }
Es möchte jedoch immer noch gut spielen und flexibel sein, wenn Sie a nicht zurückgeben möchten
Call
. Um dies zu unterstützen, hat es das Konzept einesCallAdapter
, das wissen soll, wie man aCall<Simple>
in a umwandeltSimple
.Die Verwendung von
RxJavaCallAdapterFactory
ist nur nützlich, wenn Sie versuchen, zurückzukehrenrx.Observable<Simple>
.Die einfachste Lösung besteht darin, a
Call
wie von Retrofit erwartet zurückzugeben. Sie können auch eine schreiben,CallAdapter.Factory
wenn Sie sie wirklich brauchen.quelle
Call<Simple>
es so funktioniert. Wie in meiner Frage angegeben , ist es jedoch meine Präferenz, einfach zurückzukehrenSimple
(wie es in der früheren Version der Fall war). Meine Schlussfolgerung ist : nicht möglich ohne zusätzlichen Code.Call<Simple>
ist fehlerhaft. Zu welchem PaketSimple
gehört?Simple
ist die in der OP-Frage erwähnte Klasse. Der Link ist zuCall<T>
.Im Fall von Kotlin und Coroutinen trat diese Situation auf, als ich vergaß, die API-Servicefunktion so zu markieren,
suspend
als würde ich diese Funktion aufrufen vonCoroutineScope(Dispatchers.IO).launch{}
:Verwendung:
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> }
quelle
Abhängigkeiten hinzufügen:
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'
Erstellen Sie Ihren Adapter folgendermaßen:
Retrofit rest = new Retrofit.Builder() .baseUrl(endpoint) .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) .addConverterFactory(SimpleXmlConverterFactory.create()) .build();
addCallAdapterFactory ()
undaddConverterFactory ()
beide müssen angerufen werden.Bedienung:
public interface SimpleService { @GET("/simple/{id}") Call<Simple> getSimple(@Path("id") String id); }
Ändern
Simple
inCall<Simple>
.quelle
Call
in die ServiceschnittstelleCompletableFuture
See stackoverflow.com/questions/32269064/…Mit der neuen Nachrüstung (2. +) müssen Sie addCallAdapterFactory hinzufügen, die eine normale oder eine RxJavaCallAdapterFactory (für Observables) sein kann. Ich denke, Sie können auch mehr als beides hinzufügen. Es wird automatisch überprüft, welches verwendet werden soll. Siehe ein Arbeitsbeispiel unten. Sie können diesen Link auch für weitere Details überprüfen .
Retrofit retrofit = new Retrofit.Builder().baseUrl(ApiConfig.BASE_URL) .addConverterFactory(GsonConverterFactory.create()) .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) .build()
quelle
compile 'com.squareup.retrofit:adapter-rxjava:2.0.0-beta1'
com.squareup.retrofit2:adapter-rxjava:2.1.0
undcom.squareup.retrofit2:converter-gson:2.1.0
Wenn Sie verwenden möchten
retrofit2
und nicht immer zurückkehren möchtenretrofit2.Call<T>
, müssen Sie einen eigenen erstellen, der denCallAdapter.Factory
erwarteten einfachen Typ zurückgibt. Der einfache Code kann folgendermaßen aussehen: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 } } }; } }
Dann registrieren Sie einfach das
SynchronousCallAdapterFactory
in Retrofit, um Ihr Problem zu lösen.Retrofit rest = new Retrofit.Builder() .baseUrl(endpoint) .addConverterFactory(SimpleXmlConverterFactory.create()) .addCallAdapterFactory(SynchronousCallAdapterFactory.create()) .build();
Danach können Sie einfachen Typ ohne zurückgeben
retrofit2.Call
.public interface SimpleService { @GET("/simple/{id}") Simple getSimple(@Path("id") String id); }
quelle
2.0.0-beta3
es eine Schnittstelle, jetzt in der Version ist2.1.0
es eine Klasse. Ich habe meinen Code bearbeitet, um aktueller zu sein. Vielen Dank.Simple getSimple()
undResponse<Simple> getSimple()
Anforderungen erstellt: github.com/jaredsburrows/retrofit2-synchronous-adapter .Fügen Sie die folgenden Abhängigkeiten für die Nachrüstung 2 hinzu
compile 'com.squareup.retrofit2:retrofit:2.1.0'
für GSON
compile 'com.squareup.retrofit2:converter-gson:2.1.0'
für Observablen
compile 'com.squareup.retrofit2:adapter-rxjava:2.1.0'
In Ihrem Fall für XML müssten Sie die folgenden Abhängigkeiten angeben
compile 'com.squareup.retrofit2:converter-simplexml:2.1.0'
Aktualisieren Sie den Serviceabruf wie folgt
final Retrofit rest = new Retrofit.Builder() .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) .addConverterFactory(SimpleXmlConverterFactory.create()) .baseUrl(endpoint) .build(); SimpleService service = rest.create(SimpleService.class);
quelle
in meinem Fall mit diesem
compile 'com.jakewharton.retrofit:retrofit2-rxjava2-adapter:1.0.0'
mit diesem
new Retrofit.Builder().addCallAdapterFactory(RxJava2CallAdapterFactory.create())...
löste das Problem, als nichts anderes funktionierte
quelle
Wenn Sie RxJava nicht verwenden, ist es nicht sinnvoll, RxJava nur zur Nachrüstung hinzuzufügen.
2.5.0
unterstütztCompletableFuture
integrierte Funktionen, die Sie verwenden können, ohne eine andere Bibliothek oder einen anderen Adapter hinzuzufügen.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> }
Verwendung:
Retrofit.Builder() .addConverterFactory(SimpleXmlConverterFactory.create()) .baseUrl("https://api.example.com") .build() .create(Api::class.java)
quelle
IllegalArgumentException: Aufrufadapter für Klasse java.lang.Object kann nicht erstellt werden
Kurze Antwort: Ich habe es durch die folgenden Änderungen gelöst
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"
Viel Glück
quelle
Nur um die Anrufbeispiele für Personen zu verdeutlichen, die migrieren, keinen Empfang verwenden oder synchrone Anrufe wünschen - Anruf ersetzt im Wesentlichen die Antwort (Wraps), dh:
Response<MyObject> createRecord(...);
wird
Call<MyObject> createRecord(...);
und nicht
(für die noch ein Adapter erforderlich ist)
Mit dem Anruf können Sie dann weiterhin verwenden,
isSuccessful
da tatsächlich eine Antwort zurückgegeben wird. Sie können also Folgendes tun:Oder greifen Sie auf Ihren Typ (MyObject) zu:
quelle
public interface SimpleService { @GET("/simple/{id}") Simple getSimple(@Path("id") String id); }
Die Kommunikation mit dem Netzwerk erfolgt über den separaten Thread, daher sollten Sie Ihr Simple damit ändern.
public interface SimpleService { @GET("/simple/{id}") Call<Simple> getSimple(@Path("id") String id); }
quelle
In meinem Fall habe ich verwendet
com.squareup.retrofit2:adapter-rxjava:2.5.0 //notice rxjava
anstatt
com.squareup.retrofit2:adapter-rxjava2:2.5.0 //notice rxjava2
Sie sollten bei der Verwendung
com.squareup.retrofit2:adapter-rxjava2:2.5.0
verwendenio.reactivex.rxjava2
quelle
Sie können einen Rückruf implementieren und die Funktion Einfach von onResponse abrufen.
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 } }
quelle
Die Art und Weise, wie ich dieses Problem behoben habe, bestand darin, dies zur Anwendungsgradle-Datei hinzuzufügen. Wenn die Konfiguration nicht festgelegt ist, kommt es zu Konflikten. Möglicherweise wird dies in der stabilen Version der Bibliothek behoben:
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' }
und erstellen Sie Ihren Adapter folgendermaßen:
Retrofit retrofit = new Retrofit.Builder() .baseUrl(endPoint) .addConverterFactory(SimpleXmlConverterFactory.create()) .build();
Ich hoffe es hilft!
quelle