11
votes

I'm new to RxJava/RxAndroid but I'm stuck with my use case.

I try to iterate a List<A> to convert each A into an B asynchronously (because it needs call to database) and my Observer should be notified on every successful conversion (in onNext()) to do some jobs on the main thread.

I successfully managed to convert the entire list and then received my List<B> in onNext()but I need to be notified at each item, not once all items are done.

I tried something with the operator from but if I use from(List<A>) my Observer must receivied objects from the same type (A and not B).

Here is how my code to convert entire List<A> to list<B> What should I change here?

private List<A> listOfA;

private startConversion() {
    Observer observer = new Observer<List<B>>() {
        @Override
        public void onCompleted() {

        }

        @Override
        public void onError(Throwable e) {
            e.printStackTrace();
        }

        @Override
        public void onNext(List<B> convertedItems) {
            onConversionCompleted(convertedItems);
        }
    };

    Observable<B> observervable = Observable.fromCallable(new Callable<List<B>>() {
        @Override
        public List<B> call() throws Exception {
            return convertListOfAToListOfB(listOfA);
        }
    });

    subscription = observable
                .subscribeOn(Schedulers.newThread())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(observer);
}

PS: this is pseudo code.

Thank's for help !

4

4 Answers

20
votes

If you want transform each item one by one in separate thread you can do it in this way.

    Observable.from(list)    
            .map(input -> {
                // transform each A -> B
            })
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(item -> {

            });

If you already have observable which emit list and want to transform it to sequence use this:

        listObservable
            .flatMap(Observable::from)
            .subscribe(item -> {

            });

If you want to combine this two ways and transform all values in one place but emit them one by one you can do something like this:

    Observable.create(subscriber -> {
        for (Item item : items) {
            subscriber.onNext(transformA2B(item));
        }

        subscriber.onCompleted();
    });
0
votes

Here it is.. with simple example:

public static void main(String[] args) {
    String[] s = {"a", "b", "c"};
    Observable.from(s).map(value -> "A"+value).subscribe(result -> System.out.println(result));
    Observable.timer(2, TimeUnit.SECONDS).toBlocking().subscribe();
}

As you mentioned list, I am using an array for simplicity, even list can be used as a parameter for from()

0
votes

You can also use Observable.fromIterable(list) to create a list of observables from a list. Then you can iterate over the items and convert it to a List.

 Observable.fromIterable(list)
            .filter(item -> item.getId().equals("SampleId")
            .toList();
0
votes
Observable
    //Loop through the list and emit value one by one
    .fromIterable(intList)
    //Modify the list item to new item
    .map(listItem -> listItem + 10)
    //Update UI or do anything here
    .doOnNext(System.out::println)
    //Convert to new list after modifying each item
    .toList()
    .subscribe(
        newList -> "You will get new list",
        error -> "error"
    );