0

I have an Observable<MoviesResponse>. My MovieResponse class contains a getResults() methods returning a List<Result>. This Result class has a getTitle() methods returning a String. I want to call the getTitle() methods of all my Result objects to get all the titles of my movies.

I achieved this with the code below using a foreach loop but I think there is a better way to do this by chaining RxJava operators, I just can't figure it out...

Subscription :

Observable<MoviesResponse> moviesResponseObservable = apiService.getTopRatedMoviesObservable(API_KEY);

subscription = moviesResponseObservable
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Observer<MoviesResponse>() {
                    @Override
                    public void onCompleted() {

                    }

                    @Override
                    public void onError(Throwable e) {

                    }

                    @Override
                    public void onNext(MoviesResponse moviesResponse) {
                        List<Result> results = moviesResponse.getResults();
                        for (Result r:results) {
                            Log.d(LOG_TAG,r.getTitle());
                        }
                    }
                });

Interface :

public interface ApiService {           
    @GET("movie/top_rated")
    Observable<MoviesResponse> getTopRatedMoviesObservable(@Query("api_key") String apiKey);
}

2 Answers 2

3

You can use a flatmap to transform your observable into an Observable<Result> and then use map to turn that into Observable<String>, which you can then subscribe to.

moviesReponseObservable
    .subscribeOn(Schedulers.io())
    .flatMapIterable(new Function<MoviesResponse, Iterable<Result>>() {
        @Override
        public Iterable<Result> apply(@NonNull MoviesResponse moviesResponse) throws Exception {
            return moviesResponse.getResults();
        }
    })
    .map(new Function<Result, String>() {
        @Override
        public String apply(@NonNull Result result) throws Exception {
            return result.getTitle();
        }
    })
    .observeOn(AndroidSchedulers.mainThread())
    .subscribe(new Observer<String>() {

        @Override
        public void onNext(String s) {
            Log.d("TAG", s);
        }

        /* ... */    

    });
Sign up to request clarification or add additional context in comments.

1 Comment

Thank you for your answer, it was very useful. I got this error on both new Function : map (rx.functions.Func1<? super com.example.reactiveprog.network.apimodel.Result,? extends R>) in Observable cannot be applied to (anonymous java.util.function.Function<com.example.reactiveprog.network.apimodel.Result,java.lang.String>)reason: no instance(s) of type variable(s) R exist so that Function<Result, String> conforms to Func1<? super Result, ? extends R> but find a way with Func1 following Android Studio suggestions.
1

I got the following error with @zsmb13 answer :

new Function : map (rx.functions.Func1) in Observable cannot be applied to (anonymous java.util.function.Function)reaso‌​n: no instance(s) of type variable(s) R exist so that Function conforms to Func1

Anyway this answer was very helpul I just replaced Function with Func1 and used call method.

subscription = moviesResponseObservable
                .subscribeOn(Schedulers.io())
                .flatMapIterable(new Func1<MoviesResponse, Iterable<Result>>() {
                    @Override
                    public Iterable<Result> call(MoviesResponse moviesResponse) {
                        return moviesResponse.getResults();
                    }

                })
                .map(new Func1<Result, String>() {

                    @Override
                    public String call(Result result) {
                        return result.getTitle();
                    }
                })
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Observer<String>() {


                    @Override
                    public void onCompleted() {

                    }

                    @Override
                    public void onError(Throwable e) {

                    }

                    @Override
                    public void onNext(String s) {
                        Log.d(LOG_TAG, s);
                    }
                });

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.