RxJava i Retrofit

0

Witam, mam problem z pobraniem tablicy obiektów (JSON) przy użyciu RxJavy. Rzuca mi nulla ```

  "asset_id_base": "USD",
  "rates": [
    {
      "time": "2019-09-12T17:12:16.1937202Z",
      "asset_id_quote": "OMG",
      "rate": 0.9560157008032279813595357090
    },
 ...
 ]
}

wartość "asset_id_base" udaje się pobrać natomiast przy "rates" jest ciężko
metoda GET do requesta

    Call<Rates> getCryptocurrency(@Path("asset_id_base") String base);

wywołanie z RxJava gdzie w metodzie onNext chciałem również wyciągnąć obiekty z tablicy "rates"

     service.getCryptocurrency("usd")
                .observeOn(AndroidSchedulers.mainThread())
                .subscribeOn(Schedulers.io())
                .subscribe(new Observer<Rates>() {
                    @Override
                    public void onSubscribe(Disposable d) {

                    }

                    @Override
                    public void onNext(Rates rates) {
                        Log.d(TAG, "onNext: " + rates.getAsset_id_base());

                    }

                    @Override
                    public void onError(Throwable e) {

                    }

                    @Override
                    public void onComplete() {
                    }
                });

oraz klasa Rates

public class Rates {
    @SerializedName("asset_id_base")
    private String asset_id_base;

    @SerializedName("rates")
  private List<Cryptocurrency> cryptocurrencyList;

    public List<Cryptocurrency> getCryptocurrencyList() {
        return cryptocurrencyList;
    }

    public void setCryptocurrencyList(List<Cryptocurrency> cryptocurrencyList) {
        this.cryptocurrencyList = cryptocurrencyList;
    }

    public String getAsset_id_base() {
        return asset_id_base;
    }

    public void setAsset_id_base(String asset_id_base) {
        this.asset_id_base = asset_id_base;
    }

    public Rates(String asset_id_base, List<Cryptocurrency> cryptocurrencyList) {
        this.asset_id_base = asset_id_base;
        this.cryptocurrencyList = cryptocurrencyList;
    }
}

i CryptoCurrency

public class Cryptocurrency  {
    private  String name;
    @SerializedName("time")
    @Expose
    private String time;

    @Expose
    @SerializedName("rate")
    private String rate;

    public String getRate() {
        return rate;
    }

    public void setRate(String rate) {
        this.rate = rate;
    }

    public String getTime() {
        return time;
    }

    public void setTime(String time) {
        this.time = time;
    }

    public String getName() {
        return name;
    }

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

    public Cryptocurrency(String time, String rate, String name) {
        this.time = time;
        this.rate = rate;
        this.name = name;
    }
}
0

Klasy DTO wydają się poprawne - ten JSON który podałeś pochodzi z ręcznego requestu? Sugeruję dodać interceptor do HTTP clienta, zapiąć się w nim debugerem i zobaczyć jaki surowy response przychodzi.

1

Można to wszytko pożenić w znacznie wygodniejszy sposób:

  1. Dodałem do build.gradle:
    implementation 'com.squareup.retrofit2:retrofit:2.6.1'
    implementation group: 'com.squareup.retrofit2', name: 'converter-gson', version: '2.6.1'
    implementation 'com.squareup.retrofit2:adapter-rxjava2:2.6.1'
  1. Klasy domenowe wyglądaja tak:
import java.util.List;

public class CryptoCurrency {
    public String assetIdBase;
    public List<Rate> rates = null;
}

oraz

public class Rate {
    public String time;
    public String assetIdQuote;
    public Double rate;
}

Zostały one wygenerowane poprzez http://www.jsonschema2pojo.org/ - nie pisałem ich ręcznie. Kopiuj wklej odpowiedź np z postmana do tego serwisu, zmiana trzech ustawień w prawym panelu i mamy wygenerowane klasy.

  1. Retrofitowy interfejs od serwisu:
import io.reactivex.Single;
import retrofit2.http.GET;
import retrofit2.http.Headers;

public interface CryptoService {
    @Headers("x-coinapi-key: THE_KEY")
    @GET("./")
    Single<CryptoCurrency> getCrypto();
}
  1. Na koniec klasa która wszystko łączy:
public class Parser {

    private static final String TAG = "Parser";

    public void parse() {

        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl("https://rest.coinapi.io/v1/exchangerate/USD/")
                .addConverterFactory(GsonConverterFactory.create(buildGson()))
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                .build();

        CryptoService service = retrofit.create(CryptoService.class);

        service.getCrypto()
                .subscribeOn(Schedulers.io())
                .subscribe(this::yes, this::no);
    }

    private Gson buildGson() {
        GsonBuilder gsonBuilder = new GsonBuilder();
        gsonBuilder.setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES);
        return gsonBuilder.create();
    }

    private void yes(CryptoCurrency cryptoCurrency) {
        Log.d(TAG, "Y " + cryptoCurrency.assetIdBase);

        for (Rate rate : cryptoCurrency.rates) {
            Log.d(TAG, rate.assetIdQuote + " " + rate.rate);
        }
    }

    private void no(Throwable throwable) {
        Log.d(TAG, "T " + throwable);
    }
}

1 użytkowników online, w tym zalogowanych: 0, gości: 1