我正在创建一个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() {
}
});
}
答案 0 :(得分:2)
我认为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);
}