Retrofit 2 - RxJava: невозможно вызвать конструктор без аргументов для retrofit2.Call <RemoteDataObjectModel> - PullRequest
0 голосов
/ 03 апреля 2019

Я создаю приложение для Android, и цель состоит в том, чтобы отобразить список Pokemon, который можно найти с помощью PokeApi по адресу https://pokeapi.co/

У меня есть два экземпляра, один, где он работает без RxJava2, и один, гдеон не работает с RxJava 2. В обоих случаях я использую Retrofit 2.

Поскольку, когда он не работает, когда я включаю RxJava2, я получаю ошибку:

D/thrown: java.lang.RuntimeException: Unable to invoke no-args constructor for retrofit2.Call<za.co.lbnkosi.discoveryassesment.domain.model.RemoteDataObjectModel>. Registering an InstanceCreator with Gson for this type may fix this problem.

При этомЯ рассмотрел множество вопросов Stackoverflow, похожих на этот, и большинство, если не все, упоминают десериализацию, которая для меня не сработала так долго.

Я хотел бы знать, в чем проблема или что яя делаю неправильно и как я могу решить эту проблему.Ниже я включил соответствующий код

public interface PokeApi {

    //Ignore
    @GET("pokemon")
    Call<RemoteDataObjectModel> getPokemonList(@Query("limit") int limit, @Query("offset") int offset);

    @GET("pokemon")
    Observable<Call<RemoteDataObjectModel>> getPokemonList2(@Query("limit") int limit, @Query("offset") int offset);

}
public class RemoteDataObjectModel {

    @SerializedName("results")
    private ArrayList<RemoteDataModel> results;

    public ArrayList<RemoteDataModel> getResults() {
        return results;
    }

    public void setResults(ArrayList<RemoteDataModel> results) {
        this.results = results;
    }
}
public class RemoteDataModel {

    @SerializedName("number")
    private int number;

    @SerializedName("name")
    private String name;

    @SerializedName("url")
    private String url;

    public int getNumber() {
        String[] urlItems = url.split("/");
        return Integer.parseInt(urlItems[urlItems.length -1]);
    }

    public void setNumber(int number) {
        this.number = number;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getUrl() {
        return url;
    }

    public void setUrl(String url) {
        this.url = url;
    }
}
public class RetrofitComponent {

    private static RetrofitComponent INSTANCE;
    private PokeApi pokeApi;


    private RetrofitComponent(){

        OkHttpClient okHttpClient = new OkHttpClient().newBuilder()
                .connectTimeout(60, TimeUnit.SECONDS)
                .readTimeout(60, TimeUnit.SECONDS)
                .writeTimeout(60, TimeUnit.SECONDS)
                .build();


        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl("http://pokeapi.co/api/v2/")
                .addConverterFactory(GsonConverterFactory.create())
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                .client(okHttpClient)
                .build();

         pokeApi = retrofit.create(PokeApi.class);

    }


    public static RetrofitComponent getInstance() {
        if (INSTANCE == null) {
            INSTANCE = new RetrofitComponent();
        }
        return INSTANCE;
    }

    public Observable<Call<RemoteDataObjectModel>> getPokemonList(int limit, int offest) {
        return pokeApi.getPokemonList2(30,0);
    }


}
private void getPokemonList(PokeApiDataSource.PokemonListCallback callback) {
       RetrofitComponent.getInstance()
                .getPokemonList(100,0)
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Observer<Call<RemoteDataObjectModel>>() {
                    @Override
                    public void onSubscribe(Disposable d) {

                    }

                    @Override
                    public void onNext(Call<RemoteDataObjectModel> remoteDataObjectModelCall) {
                        Log.d("","");
                        remoteDataObjectModelCall.enqueue(new Callback<RemoteDataObjectModel>() {
                            @Override
                            public void onResponse(@NotNull Call<RemoteDataObjectModel> call, @NotNull Response<RemoteDataObjectModel> response) {
                                loading = true;
                                RemoteDataObjectModel pokeApiObjects = response.body();
                                _arrayList = Objects.requireNonNull(pokeApiObjects).getResults();
                                callback.pokemonListSuccess();
                            }
                            @Override
                            public void onFailure(@NotNull Call<RemoteDataObjectModel> call, @NotNull Throwable t) {
                                loading = true;
                                Log.e(TAG, " onFailure: " + t.getMessage());
                            }
                        });
                    }

                    @Override
                    public void onError(Throwable e) {
                        Log.d("thrown", e.toString());
                    }

                    @Override
                    public void onComplete() {

                    }
                });
    }

1 Ответ

2 голосов
/ 03 апреля 2019

Я думаю, Call это класс из Retrofit. Он предоставляет функцию обратного вызова для асинхронного получения ответа. Но так как вы собираетесь использовать RxJava, природа Rxjava уже асинхронна. Возможно, вам не нужно получать ответ как Call. Вместо этого, пожалуйста, попробуйте это

public interface PokeApi {

   // If you need to get the response body + headers ...
    @GET("pokemon")
    Observable<Response<RemoteDataObjectModel>> getPokemonList2(@Query("limit") int limit, @Query("offset") int offset);


   // If you only need body
    @GET("pokemon")
    Observable<RemoteDataObjectModel> getPokemonList2(@Query("limit") int limit, @Query("offset") int offset);

   // Or the better way, the result from API is only return once. So, Single is more suitable in this case
    @GET("pokemon")
    Single<RemoteDataObjectModel> getPokemonList2(@Query("limit") int limit, @Query("offset") int offset);

}
...