• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

question-closed Retrofit + Rxjava. Problem z funkcją Observable.zip()

Object Storage Arubacloud
0 głosów
220 wizyt
pytanie zadane 28 listopada 2018 w Java przez Micheall Początkujący (420 p.)
zamknięte 29 listopada 2018 przez Micheall

Witam. W aplikacji Android próbuję wykonać kilka zapytań za pomocą biblioteki Retrofit , żeby pobrać dane w formacie JSON z endpointa na przeglądarce. Żeby zsynchronizować zapytania używam biblioteki Rxjava. Próbuję zrobić to w ten sposób że tworzę dynamicznie listę obiektów Observable a następnie przesyłam je do funkcji Observable.zip() żeby ze wszystkich danych zrobić jeden obiekt, a następnie za pomocą funkcji subscribe() wykorzystać dane z tego obiektu. Niestety ciągle mam błąd w funkcji Observable.zip() . Szukałem długo po internecie rozwiązania ale zazwyczaj są niekompletne lub przestarzałe. Proszę o pomoc i z góry dziękuję :) . Zamieszczam mój kod:

            //Tworze liste Observable 
            final List<Observable<PojoData>> requests = new ArrayList<>();

            //Tworze dynamicznie zapytania Retrofit i dodaje je do listy Observable
            Iterator iter = nodesId.iterator();
            while (iter.hasNext()) {
                int nodeNumber = (int) iter.next();
                requests.add(service.getData("data",String.valueOf(nodeNumber), String.valueOf(minDay)+","+ String.valueOf(maxDay)));
            }

            //Funkcja zip w ktorej jest blad
            Observable<PojoAllSecondActivity> combined = Observable.zip(requests, new Function<PojoData[], PojoAllSecondActivity>() {
                @Override
                public PojoAllSecondActivity apply(PojoData[] pojoData) throws Exception {
                    return new PojoAllSecondActivity(Arrays.asList(pojoData));
                }
            });

            // obiekt Consumer do pozniejszej funkcji subscribe()
            Consumer<PojoAllSecondActivity> subscriber = new Consumer<PojoAllSecondActivity>() {
                @Override
                public void accept(PojoAllSecondActivity pojoAllSecondActivity) throws Exception {
                    Log.d(TAG, "accept:  " + pojoAllSecondActivity.getPojoDataList().get(0).getDataOutputs().get(0).getCreatedat());
                }
            };

            //subscribe()
            combined.subscribeOn(Schedulers.io())
                    .observeOn(AndroidSchedulers.mainThread())
                    .subscribe(subscriber);

Klasa PojoAllSecondActivity:

public class PojoAllSecondActivity {
    public List<PojoData> pojoDataList;

    public PojoAllSecondActivity(List<PojoData> pojoDataList) {
        this.pojoDataList = pojoDataList;
    }

    public List<PojoData> getPojoDataList() {
        return pojoDataList;
    }

    public void setPojoDataList(List<PojoData> pojoDataList) {
        this.pojoDataList = pojoDataList;
    }
}

Klasa PojoData:

public class PojoData {

    @SerializedName("output")
    @Expose
    private List<DataOutput> dataOutputs = null;

    public List<DataOutput> getDataOutputs() {
        return dataOutputs;
    }

    public void setOutput(List<DataOutput> dataOutputs) {
        this.dataOutputs = dataOutputs;
    }

}

 

komentarz zamknięcia: Otrzymałem odpowiedź.

1 odpowiedź

+1 głos
odpowiedź 29 listopada 2018 przez KubenQPL Maniak (62,820 p.)
wybrane 29 listopada 2018 przez Micheall
 
Najlepsza

Możesz to zrobić prościej:

Observable.concat(requests)
    .toList()
 

Co będzie typem Observable<List<PojoData>> więc w onNext dostaniesz już List<PojoData>.

Poza tym zapytania z retrofita są wykonywane raz więc możesz użyć Single zamiast Observable i zrobić tak samo jak powyżej podałem

komentarz 29 listopada 2018 przez Micheall Początkujący (420 p.)

Dzięki ! Ostatecznie jednak wczoraj udało mi się zmieniająć PojoData[] na Object[] tak jak poniżej, chociaż nie mam pojęcia czemu dopiero to zadziałało.  Mógłbyś mi jeszcze wytłumaczyć czy w tej sytuacji lepiej użyć Single czy to bez znaczenia skoro działa? Bo jak rozumiem te zapytania HTTP są wykonywane równocześnie asynchronicznie a funkcja zip() czeka aż każde zapytanie się zakończy i zbiera z nich wyniki? :) Jestem początkujący w tym :)

Observable<PojoAllSecondActivity> combined = Observable.zip(requests, new Function<Object[], PojoAllSecondActivity>() {
                @Override
                public PojoAllSecondActivity apply(Object[] objects) throws Exception {
                    ArrayList<PojoData> pojoDataArrayList = new ArrayList<>();
                    for (Object o : objects) {
                        pojoDataArrayList.add((PojoData) o);
                    }
                    return new PojoAllSecondActivity(pojoDataArrayList);
                }
            });

 

komentarz 29 listopada 2018 przez KubenQPL Maniak (62,820 p.)

Do zwykłych zapytań http nie ma potrzeby używania Observable bo masz jedną odpowiedź z jednego zapytania, więc w tym wypadku lepiej użyć Single. Single to takie Observable w którym onNext jest wywołane tylko raz. Czyli zamiast Consumerów dla onNext, onComplete oraz onError masz samo onSuccess i onError, tu bardziej chodzi o czystość kodu i eliminowanie niepotrzebnych elementów.

Jeśli chodzi zaś o zip vs concat -> concat zwraca Flowable i wykonuje po kolei wszystkie Single/Observable które były użyte w tym concat i zwraca ich wartości po kolei w onNext, tyle że używając .toList() to samo agreguje ci wynik z onNext w jedną listę zwróconych wartości i zwraca ją w onSuccess. Zip zaś wykonuje wszystko równolegle i zwraca wszystkie wyniki dopiero gdy wszystkie SingleObservable zostaną zakończone.

Więc dla czystości lepiej użyć powyższego rozwiązania z Single i concat. A jeśli potrzebujesz wykonania równoległego to możesz dodatkowo wywołać parallel() po concat.

Single.concat(requests)
    .parallel()
    .toList()

 

komentarz 29 listopada 2018 przez Micheall Początkujący (420 p.)
Rozumiem. Dzięki jeszcze raz :)

Podobne pytania

0 głosów
0 odpowiedzi 208 wizyt
pytanie zadane 5 grudnia 2018 w Android, Swift, Symbian przez Micheall Początkujący (420 p.)
0 głosów
0 odpowiedzi 248 wizyt
0 głosów
2 odpowiedzi 343 wizyt
pytanie zadane 2 marca 2020 w JavaScript przez Ehlert Ekspert (212,870 p.)

92,654 zapytań

141,543 odpowiedzi

319,953 komentarzy

62,022 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj.

Akademia Sekuraka

Kolejna edycja największej imprezy hakerskiej w Polsce, czyli Mega Sekurak Hacking Party odbędzie się już 20 maja 2024r. Z tej okazji mamy dla Was kod: pasjamshp - jeżeli wpiszecie go w koszyku, to wówczas otrzymacie 40% zniżki na bilet w wersji standard!

Więcej informacji na temat imprezy znajdziecie tutaj. Dziękujemy ekipie Sekuraka za taką fajną zniżkę dla wszystkich Pasjonatów!

Akademia Sekuraka

Niedawno wystartował dodruk tej świetnej, rozchwytywanej książki (około 940 stron). Mamy dla Was kod: pasja (wpiszcie go w koszyku), dzięki któremu otrzymujemy 10% zniżki - dziękujemy zaprzyjaźnionej ekipie Sekuraka za taki bonus dla Pasjonatów! Książka to pierwszy tom z serii o ITsec, który łagodnie wprowadzi w świat bezpieczeństwa IT każdą osobę - warto, polecamy!

...