Невозможно создать адаптер вызова для примера класса. Простой
Я использую retrofit 2.0.0-beta1 с SimpleXml. Я хочу получить простой (XML) ресурс из службы REST.
Marshalling/Unmarshalling простого объекта с SimpleXML отлично работает.
При использовании этого кода (преобразованный формат 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"));
Услуги:
public interface SimpleService {
@GET("/simple/{id}")
Simple getSimple(@Path("id") String id);
}
Я получаю это исключение:
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)
Что мне не хватает? Я знаю, что обработка возвращаемого типа выполняется с помощью Call
. Но я хочу, чтобы служба возвращала бизнес-объекты как тип (и работала в режиме синхронизации).
UPDATE
После добавления дополнительных зависимостей и .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
, как это было предложено разными ответами, я все равно получаю эту ошибку:
Caused by: java.lang.IllegalArgumentException: Could not locate call adapter for class simple.Simple. Tried:
* retrofit.RxJavaCallAdapterFactory
* retrofit.DefaultCallAdapter$1
Ответы
Ответ 1
Короткий ответ: верните Call<Simple>
в свой сервисный интерфейс.
Похоже, Retrofit 2.0 пытается найти способ создания прокси-объекта для вашего сервисного интерфейса. Он ожидает, что вы напишете это:
public interface SimpleService {
@GET("/simple/{id}")
Call<Simple> getSimple(@Path("id") String id);
}
Однако он все еще хочет играть хорошо и быть гибким, если вы не хотите возвращать Call
. Чтобы поддержать это, в нем есть концепция CallAdapter
, которая должна знать, как адаптировать Call<Simple>
в Simple
.
Использование RxJavaCallAdapterFactory
полезно, только если вы пытаетесь вернуть rx.Observable<Simple>
.
Самое простое решение - вернуть a Call
, как ожидает Retrofit. Вы также можете написать CallAdapter.Factory
, если вам это действительно нужно.
Ответ 2
добавить зависимости:
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'
создайте свой адаптер следующим образом:
Retrofit rest = new Retrofit.Builder()
.baseUrl(endpoint)
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.addConverterFactory(SimpleXmlConverterFactory.create())
.build();
addCallAdapterFactory ()
и addConverterFactory ()
оба должны быть вызваны.
Услуги:
public interface SimpleService {
@GET("/simple/{id}")
Call<Simple> getSimple(@Path("id") String id);
}
Измените Simple
на Call<Simple>
.
Ответ 3
С новой модификацией (2. +) вам нужно добавить addCallAdapterFactory, который может быть нормальным или RxJavaCallAdapterFactory (для Observables). Я думаю, вы можете добавить больше, чем оба. Он автоматически проверяет, какой из них использовать. См. Рабочий пример ниже. Вы также можете проверить эту ссылку для получения более подробной информации.
Retrofit retrofit = new Retrofit.Builder().baseUrl(ApiConfig.BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.build()
Ответ 4
Добавьте следующие зависимости для модификации 2
compile 'com.squareup.retrofit2:retrofit:2.1.0'
для GSON
compile 'com.squareup.retrofit2:converter-gson:2.1.0'
для наблюдаемых
compile 'com.squareup.retrofit2:adapter-rxjava:2.1.0'
В вашем случае для XML вам нужно будет включить следующие зависимости
compile 'com.squareup.retrofit2:converter-simplexml:2.1.0'
Обновить служебный вызов ниже
final Retrofit rest = new Retrofit.Builder()
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.addConverterFactory(SimpleXmlConverterFactory.create())
.baseUrl(endpoint)
.build();
SimpleService service = rest.create(SimpleService.class);
Ответ 5
Если вы хотите использовать retrofit2
, и вы не хотите всегда возвращать retrofit2.Call<T>
, вам нужно создать свой собственный CallAdapter.Factory
, который возвращает простой тип, как вы ожидали. Простой код может выглядеть так:
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
}
}
};
}
}
Тогда простой регистр SynchronousCallAdapterFactory
в Retrofit должен решить вашу проблему.
Retrofit rest = new Retrofit.Builder()
.baseUrl(endpoint)
.addConverterFactory(SimpleXmlConverterFactory.create())
.addCallAdapterFactory(SynchronousCallAdapterFactory.create())
.build();
После этого вы можете вернуть простой тип без retrofit2.Call
.
public interface SimpleService {
@GET("/simple/{id}")
Simple getSimple(@Path("id") String id);
}
Ответ 6
в моем случае, используя этот
compile 'com.jakewharton.retrofit:retrofit2-rxjava2-adapter:1.0.0'
с этим
new Retrofit.Builder().addCallAdapterFactory(RxJava2CallAdapterFactory.create())...
решил проблему, когда ничего не работало
Ответ 7
Просто чтобы сделать примеры вызовов более понятными для людей, которые мигрируют, не используют Rx или хотят синхронные вызовы - Call по существу заменяет (оборачивает) Response, что означает:
Response<MyObject> createRecord(...);
становится
Call<MyObject> createRecord(...);
и не
Call<Response<MyObject>> createRecord(...);
(для которого все еще потребуется адаптер)
Вызов затем позволит вам по-прежнему использовать isSuccessful
поскольку он на самом деле возвращает ответ. Таким образом, вы можете сделать что-то вроде:
myApi.createRecord(...).execute().isSuccessful()
Или доступ к вашему типу (MyObject), как:
MyObject myObj = myApi.createRecord(...).execute().body();
Ответ 8
Вы можете реализовать обратный вызов, получить функцию Simple from 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
}
}
Ответ 9
public interface SimpleService {
@GET("/simple/{id}")
Simple getSimple(@Path("id") String id);
}
Связь с сетью осуществляется с помощью отдельного потока, поэтому вы должны изменить свой Simple с этим.
public interface SimpleService {
@GET("/simple/{id}")
Call<Simple> getSimple(@Path("id") String id);
}
Ответ 10
В моем случае я использовал
com.squareup.retrofit2:adapter-rxjava:2.5.0 //notice rxjava
вместо
com.squareup.retrofit2:adapter-rxjava2:2.5.0 //notice rxjava2
вы должны использовать com.squareup.retrofit2:adapter-rxjava2:2.5.0
при использовании io.reactivex.rxjava2
Ответ 11
Если вы не используете RxJava, то нет смысла добавлять RxJava только для модернизации. 2.5.0
имеет встроенную поддержку CompletableFuture
которую вы можете использовать без добавления какой-либо другой библиотеки или адаптера.
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>
}
Использование:
Retrofit.Builder()
.addConverterFactory(SimpleXmlConverterFactory.create())
.baseUrl("https://api.example.com")
.build()
.create(Api::class.java)
Ответ 12
для последних модификаций (июль/2017):
Используйте версии библиотеки правильно.
Новая версия
compile 'io.reactivex.rxjava2:rxandroid:2.0.1'
compile 'io.reactivex.rxjava2:rxjava:2.1.0'
compile 'com.squareup.retrofit2:retrofit:2.3.0'
compile 'com.squareup.retrofit2:adapter-rxjava2:2.3.0'
1) Убедитесь, что у вас есть аналогичные адаптеры для дооснащения и повторной настройки RxJava.
2) Использовать
compile 'com.squareup.retrofit2:adapter-rxjava2:2.3.0'
не
compile 'com.squareup.retrofit2:adapter-rxjava:2.3.0'
Ответ 13
То, как я исправил эту проблему, добавлял это в файл приложения gradle, если конфигурация не установлена, будут конфликты, возможно, это будет исправлено в стабильной версии библиотеки:
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'
}
и создайте адаптер следующим образом:
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(endPoint)
.addConverterFactory(SimpleXmlConverterFactory.create())
.build();
Надеюсь, что это поможет!