【问题标题】:Retrofit 2 - RxJava : Unable to invoke no-args constructor for retrofit2.Call<RemoteDataObjectModel>Retrofit 2 - RxJava:无法为 retrofit2.Call<RemoteDataObjectModel> 调用无参数构造函数
【发布时间】:2019-08-24 08:28:32
【问题描述】:

我正在创建一个 Android 应用程序,目标是显示可以使用 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() {

                    }
                });
    }

【问题讨论】:

    标签: java android gson retrofit2 rx-java2


    【解决方案1】:

    我认为Call 是来自Retrofit 的类。它提供了一个回调函数来异步获取响应。但是由于你要使用RxJavaRxjava 的性质已经是异步的。您可能不需要以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);
    
    }
    

    【讨论】:

    • 非常感谢cynw,完美的答案。第一个带有响应的 Observable 有效。当我开始工作时,我会尝试其他的。再次,非常感谢
    猜你喜欢
    • 2020-02-14
    • 2020-06-15
    • 2018-12-29
    • 2017-12-20
    • 1970-01-01
    • 2016-02-18
    • 1970-01-01
    • 2021-09-25
    • 2015-08-02
    相关资源
    最近更新 更多