Не удалось создать адаптер вызова для примера класса.Простой
Я использую retrofit 2.0.0-beta1 с SimpleXml. Я хочу получить простой (XML) ресурс из службы REST.
Кроссировка/обратный простого объекта при помощи SimpleXML работает отлично.
при использовании этого кода (преобразованная форма до 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.invoke(Retrofit.java:127)
at com.sun.proxy.$Proxy0.getSimple(Unknown Source)
что я упустил? Я знаю, что обертывание возвращаемого типа с помощью Call строительство. Но я хочу, чтобы служба вернула бизнес объекты как тип (и работает в режиме синхронизации).
обновление
после добавления дополнительных зависимостей и .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) как предполагают разные ответы, я все еще получаю эту ошибку:
Caused by: java.lang.IllegalArgumentException: Could not locate call adapter for class simple.Simple. Tried:
* retrofit.RxJavaCallAdapterFactory
* retrofit.DefaultCallAdapter
9 ответов:
короткий ответ: возвращение
Call<Simple>в интерфейс сервиса.похоже, Ретрофит 2.0 пытается найти способ создания прокси-объекта для вашего интерфейса. Он ожидает, что вы напишете это:
public interface SimpleService { @GET("/simple/{id}") Call<Simple> getSimple(@Path("id") String id); }тем не менее, он все еще хочет играть красиво и быть гибким, когда вы не хотите возвращать
Call. Чтобы поддержать это, он имеет понятиеCallAdapter, который должен знать, как адаптировать aCall<Simple>в aSimple.использование
RxJavaCallAdapterFactoryполезно только в том случае, если вы пытаетесь вернутьrx.Observable<Simple>.самое простое решение-вернуть
Callкак модернизация ожидает. Вы также можете написатьCallAdapter.Factoryесли вам это действительно нужно.
добавить зависимостей:
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>.
С новой модификацией(2.+ ) вам нужно добавить addCallAdapterFactory, который может быть обычным или RxJavaCallAdapterFactory(для наблюдаемых). Я думаю, что вы можете добавить больше, чем слишком. Он автоматически проверяет, какой из них использовать. См. рабочий пример ниже. Вы также можете проверить этой ссылке для более подробной информации.
Retrofit retrofit = new Retrofit.Builder().baseUrl(ApiConfig.BASE_URL) .addConverterFactory(GsonConverterFactory.create()) .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) .build()
добавьте следующие зависимости для retrofit 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);
если вы хотите использовать
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 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); }
в моем случае с помощью этого
compile 'com.jakewharton.retrofit:retrofit2-rxjava2-adapter:1.0.0'С
new Retrofit.Builder().addCallAdapterFactory(RxJava2CallAdapterFactory.create())...решил проблему, когда больше ничего не работало
вы можете реализовать обратный вызов, получить простой из функции 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 } }
просто чтобы сделать примеры вызовов более понятными для людей, которые мигрируют, не используя Rx, или которые хотят синхронные вызовы-вызов по существу заменяет (обертывает) ответ, что означает:
Response<MyObject> createRecord(...);становится
Call<MyObject> createRecord(...);, а не
Call<Response<MyObject>> createRecord(...);(который по-прежнему требует адаптера)
вызов позволит вам по-прежнему использовать
isSuccessfulкак это на самом деле возвращает ответ. Так что вы можете сделать что-то вроде:myApi.createRecord(...).execute().isSuccessful()или доступ к ваш тип (MyObject), как:
MyObject myObj = myApi.createRecord(...).execute().body();
способ, которым я исправил эту проблему, добавлял это в файл приложения 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();надеюсь, что это помогает!
Comments