改造2-RxJava:无法为Retrofit2.Call <remotedataobjectmodel>

时间:2019-04-02 22:38:07

标签: java android gson retrofit2 rx-java2

我正在创建一个Android应用,目的是显示可以在https://pokeapi.co/上使用PokeApi找到的Pokemon列表。

我有两个实例,一个实例在没有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 个答案:

答案 0 :(得分:2)

我认为CallRetrofit的班级。它提供了一个回调函数来异步获取响应。但是由于您将使用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);

}