ventana - interfaz grafica java swing
No se puede crear el adaptador de llamada para el ejemplo de clase. (12)
Estoy usando retrofit 2.0.0-beta1 con SimpleXml. Quiero recuperar un recurso Simple (XML) de un servicio REST. Alinear / Descomponer el objeto Simple con SimpleXML funciona bien.
Al usar este código (código convertido de forma pre 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"));
Servicio:
public interface SimpleService {
@GET("/simple/{id}")
Simple getSimple(@Path("id") String id);
}
Me sale esta excepción:
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é me estoy perdiendo?
Sé que envolver el tipo de retorno por una
Call
funciona.
Pero quiero que el servicio devuelva objetos comerciales como tipo (y que funcione en modo de sincronización).
ACTUALIZAR
Después de agregar las dependencias adicionales y
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
como lo sugieren diferentes respuestas, sigo recibiendo este error:
Caused by: java.lang.IllegalArgumentException: Could not locate call adapter for class simple.Simple. Tried:
* retrofit.RxJavaCallAdapterFactory
* retrofit.DefaultCallAdapter$1
Agregue las siguientes dependencias para la actualización 2
compile ''com.squareup.retrofit2:retrofit:2.1.0''
para GSON
compile ''com.squareup.retrofit2:converter-gson:2.1.0''
para observables
compile ''com.squareup.retrofit2:adapter-rxjava:2.1.0''
En su caso para XML, debería incluir las siguientes dependencias
compile ''com.squareup.retrofit2:converter-simplexml:2.1.0''
Actualice la llamada de servicio de la siguiente manera
final Retrofit rest = new Retrofit.Builder()
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.addConverterFactory(SimpleXmlConverterFactory.create())
.baseUrl(endpoint)
.build();
SimpleService service = rest.create(SimpleService.class);
Con el nuevo Retrofit (2. +) necesita agregar addCallAdapterFactory, que puede ser normal o RxJavaCallAdapterFactory (para Observables). Creo que también puedes agregar más que ambos. Comprueba automáticamente cuál usar. Vea un ejemplo de trabajo a continuación. También puede consultar este enlace para más detalles.
Retrofit retrofit = new Retrofit.Builder().baseUrl(ApiConfig.BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.build()
En mi caso usé
com.squareup.retrofit2:adapter-rxjava:2.5.0 //notice rxjava
en lugar de
com.squareup.retrofit2:adapter-rxjava2:2.5.0 //notice rxjava2
debería usar
com.squareup.retrofit2:adapter-rxjava2:2.5.0
cuando usa
io.reactivex.rxjava2
La forma en que solucioné este problema fue agregando esto al archivo gradle de la aplicación, si la configuración no está configurada habrá conflictos, tal vez esto se solucionará en la versión estable de la biblioteca:
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''
}
y crea tu adaptador de esta manera:
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(endPoint)
.addConverterFactory(SimpleXmlConverterFactory.create())
.build();
¡Espero eso ayude!
Puede implementar una devolución de llamada, obtener la función 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
}
}
Respuesta corta: devuelve
Call<Simple>
en tu interfaz de servicio.
Parece que Retrofit 2.0 está tratando de encontrar una forma de crear el objeto proxy para su interfaz de servicio. Espera que escribas esto:
public interface SimpleService {
@GET("/simple/{id}")
Call<Simple> getSimple(@Path("id") String id);
}
Sin embargo, todavía quiere jugar bien y ser flexible cuando no desea devolver una
Call
.
Para respaldar esto, tiene el concepto de un
CallAdapter
, que se supone que sabe cómo adaptar una
Call<Simple>
a
Simple
.
El uso de
RxJavaCallAdapterFactory
solo es útil si está intentando devolver
rx.Observable<Simple>
.
La solución más simple es devolver una
Call
como espera Retrofit.
También puede escribir un
CallAdapter.Factory
si realmente lo necesita.
Si desea utilizar
retrofit2
y no siempre desea devolver
retrofit2.Call<T>
, debe crear su propio
CallAdapter.Factory
que devuelve el tipo simple como esperaba.
El código simple puede verse así:
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
}
}
};
}
}
Luego, el simple registro de
SynchronousCallAdapterFactory
en Retrofit debería resolver su problema.
Retrofit rest = new Retrofit.Builder()
.baseUrl(endpoint)
.addConverterFactory(SimpleXmlConverterFactory.create())
.addCallAdapterFactory(SynchronousCallAdapterFactory.create())
.build();
Después de eso, puede devolver el tipo simple sin
retrofit2.Call
.
public interface SimpleService {
@GET("/simple/{id}")
Simple getSimple(@Path("id") String id);
}
Si no está utilizando RxJava, no tiene sentido agregar RxJava solo para la actualización.
2.5.0
tiene soporte para
CompletableFuture
integrado en el que puede usar sin agregar ninguna otra biblioteca o adaptador.
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>
}
Uso:
Retrofit.Builder()
.addConverterFactory(SimpleXmlConverterFactory.create())
.baseUrl("https://api.example.com")
.build()
.create(Api::class.java)
Solo para aclarar los ejemplos de llamadas para las personas que están migrando, que no usan Rx o que desean llamadas sincrónicas: la llamada esencialmente reemplaza (ajusta) la respuesta, lo que significa:
Response<MyObject> createRecord(...);
se convierte
Call<MyObject> createRecord(...);
y no
Call<Response<MyObject>> createRecord(...);
(que aún requerirá un adaptador)
La Llamada le permitirá seguir usando
isSuccessful
ya que en realidad devuelve una Respuesta.
Entonces puedes hacer algo como:
myApi.createRecord(...).execute().isSuccessful()
O acceda a su Tipo (MyObject) como:
MyObject myObj = myApi.createRecord(...).execute().body();
agregar dependencias:
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''
cree su adaptador de esta manera:
Retrofit rest = new Retrofit.Builder()
.baseUrl(endpoint)
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.addConverterFactory(SimpleXmlConverterFactory.create())
.build();
addCallAdapterFactory ()
y
addConverterFactory ()
necesitan ser llamados.
Servicio:
public interface SimpleService {
@GET("/simple/{id}")
Call<Simple> getSimple(@Path("id") String id);
}
Modifique
Simple
to
Call<Simple>
.
en mi caso usando esto
compile ''com.jakewharton.retrofit:retrofit2-rxjava2-adapter:1.0.0''
con este
new Retrofit.Builder().addCallAdapterFactory(RxJava2CallAdapterFactory.create())...
resolvió el problema cuando nada más funcionaba
public interface SimpleService {
@GET("/simple/{id}")
Simple getSimple(@Path("id") String id);
}
La comunicación con la red se realiza con el hilo separado, por lo que debe cambiar su Simple con eso.
public interface SimpleService {
@GET("/simple/{id}")
Call<Simple> getSimple(@Path("id") String id);
}