Не удалось создать адаптер вызова для примера класса.Простой



Я использую 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
1136   9  

9 ответов:

короткий ответ: возвращение Call<Simple> в интерфейс сервиса.

похоже, Ретрофит 2.0 пытается найти способ создания прокси-объекта для вашего интерфейса. Он ожидает, что вы напишете это:

public interface SimpleService {
    @GET("/simple/{id}")
    Call<Simple> getSimple(@Path("id") String id);
}

тем не менее, он все еще хочет играть красиво и быть гибким, когда вы не хотите возвращать Call. Чтобы поддержать это, он имеет понятие CallAdapter, который должен знать, как адаптировать a Call<Simple> в a Simple.

использование 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

    Ничего не найдено.