Я использую модификацию 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$1.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$1
java
rest
retrofit
simple-framework
Рмюллер
источник
источник
Ответы:
Короткий ответ: вернитесь
Call<Simple>
в свой сервисный интерфейс.Похоже, Retrofit 2.0 пытается найти способ создания прокси-объекта для интерфейса вашей службы. Ожидается, что вы напишете это:
public interface SimpleService { @GET("/simple/{id}") Call<Simple> getSimple(@Path("id") String id); }
Однако он по-прежнему хочет играть хорошо и быть гибким, когда вы не хотите возвращать
Call
. Чтобы поддержать это, у него есть концепция aCallAdapter
, которая должна знать, какCall<Simple>
преобразовать a вSimple
.Использование
RxJavaCallAdapterFactory
полезно только в том случае, если вы пытаетесь вернутьсяrx.Observable<Simple>
.Самое простое решение - вернуть в
Call
соответствии с требованиями Retrofit. Вы также можете написать,CallAdapter.Factory
если вам это действительно нужно.источник
Call<Simple>
как это работает. Однако, как указано в моем вопросе, я предпочитаю просто вернутьсяSimple
(как было в более ранней версии). Мой вывод такой: : невозможно без дополнительного кода.Call<Simple>
работает. К какому пакетуSimple
относится?Simple
- это класс, упомянутый в вопросе OP. Ссылка наCall<T>
.В случае Kotlin и сопрограмм эта ситуация произошла, когда я забыл отметить служебную функцию api,
suspend
когда я вызываю эту функцию изCoroutineScope(Dispatchers.IO).launch{}
:Применение:
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> }
источник
добавить зависимости:
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>
.источник
Call
в интерфейс службыCompletableFuture
См stackoverflow.com/questions/32269064/...В новом Retrofit (2. +) вам нужно добавить addCallAdapterFactory, который может быть обычным или RxJavaCallAdapterFactory (для Observables). Я думаю, вы тоже можете добавить больше, чем оба. Он автоматически проверяет, какой из них использовать. См. Рабочий пример ниже. Вы также можете проверить эту ссылку для получения более подробной информации.
Retrofit retrofit = new Retrofit.Builder().baseUrl(ApiConfig.BASE_URL) .addConverterFactory(GsonConverterFactory.create()) .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) .build()
источник
compile 'com.squareup.retrofit:adapter-rxjava:2.0.0-beta1'
com.squareup.retrofit2:adapter-rxjava:2.1.0
иcom.squareup.retrofit2:converter-gson:2.1.0
Если вы хотите использовать
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); }
источник
2.0.0-beta3
это был интерфейс, теперь в версии2.1.0
это класс. Я отредактировал свой код, чтобы он был более актуальным. Спасибо.Simple getSimple()
иResponse<Simple> getSimple()
запросов: github.com/jaredsburrows/retrofit2-synchronous-adapter .Добавьте следующие зависимости для модернизации 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);
источник
в моем случае используя это
compile 'com.jakewharton.retrofit:retrofit2-rxjava2-adapter:1.0.0'
с этим
new Retrofit.Builder().addCallAdapterFactory(RxJava2CallAdapterFactory.create())...
решил проблему, когда ничего не работало
источник
Если вы не используете 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)
источник
IllegalArgumentException: невозможно создать адаптер вызова для класса java.lang.Object
Краткий ответ: я решил это следующими изменениями
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"
Удачи
источник
Просто чтобы сделать примеры Call более понятными для людей, которые мигрируют, не используют Rx или хотят синхронные вызовы - Call по существу заменяет (обертывает) Response, что означает:
Response<MyObject> createRecord(...);
становится
Call<MyObject> createRecord(...);
и нет
(для чего по-прежнему потребуется адаптер)
Затем Call позволит вам использовать,
isSuccessful
поскольку фактически возвращает Response. Итак, вы можете сделать что-то вроде:Или получите доступ к своему типу (MyObject), например:
источник
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); }
источник
В моем случае я использовал
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
источник
Вы можете реализовать обратный вызов, получить Simple из функции 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 } }
источник
Я исправил эту проблему, добавив это в файл 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();
Надеюсь, это поможет!
источник