RxJava flatMapIterable с concatMap

У меня есть 2 звонка для модернизации, которые мне нужны для A & B:

(A): возвращает ArrayList

(B): получает результат (A), который является ArrayList. (B) перебирает ArrayList и выполняет вызов дооснащения, используя каждый из них, и объединяет полученные данные в окончательный ArrayList, который отправляется моему подписчику onNext()

Мне удалось заставить его работать с flatmap, но решение не очень элегантное. Насколько я понимаю, лучшим решением было бы использование flatMapIterable с concatMap, но я не могу принять то, что у меня работает, для flatMapIterable с concatMap.

ServiceFactory.createRetrofitService().getUserFollowing(sessionMgr.getAuthToken())
                .flatMap(new Func1<UserSelfFollows, Observable<? extends ArrayList<Media.MediaData>>>() {
                    @Override
                    public Observable<? extends ArrayList<Media.MediaData>> call(UserSelfFollows userSelfFollows) {

                        //make second requests based on response from First request to get all Users
                        ArrayList<Media.MediaData> arAllMedia = new ArrayList<>();
                        for(UserSelfFollows.UserDataFollows user : userSelfFollows.userdata){

                            Response <ResponseBody> response ;
                            Call <ResponseBody> call;
                            try {
                                call = ServiceFactory.createRetrofitService().getMediaOfUser(user.id,sessionMgr.getAuthToken());
                                response =  call.execute();
                            }catch(IOException ex){
                                return Observable.error(ex);
                            }

                            if (response.isSuccessful()) {

                                try {
                                    String str = responseHelper.streamToString( response.body().byteStream());
                                    Gson gson = new GsonBuilder().create();
                                    Media media = gson.fromJson(str, Media.class);

                                    arAllMedia.addAll(media.mediaData);

                                } catch (IOException e) {
                                    return Observable.error(e);
                                }
                            } else {
                                return Observable.error( new Exception(  responseHelper.getErrorString( response.errorBody().byteStream())) );
                            }
                        }
                        return Observable.just(arAllMedia);

                    }
                })
                .subscribeOn(Schedulers.newThread())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Subscriber<ArrayList<Media.MediaData>>() {
                    @Override
                    public final void onCompleted() {

                    }

                    @Override
                    public final void onError(Throwable e) {

                    }

                    @Override
                    public final void onNext(ArrayList<Media.MediaData> arMedia) {

                    }
                })

Вот что у меня есть, но оно не скомпилируется:

ServiceFactory.createRetrofitService().getUserFollowing(sessionMgr.getAuthToken())
            .flatMapIterable(new Func1<UserSelfFollows, Iterable<?>>() {
                @Override
                public Iterable<?> call(UserSelfFollows userSelfFollows) {
                    return userSelfFollows.userdata;
                }
            })
            .<Media.MediaData>flatMap(new Func1<UserSelfFollows.UserDataFollows, Observable<Media.MediaData>>() {
                @Override
                public Observable<Media.MediaData> call(UserSelfFollows.UserDataFollows user) {
                    return ServiceFactory.createRetrofitService().getMediaOfUser(user.id, sessionMgr.getAuthToken());
                }
            })
            .toList();

Ошибка:

введите описание изображения здесь

3 ответа

Если я правильно понимаю ваш сценарий, вы можете использовать flatMapIterable, а потом flatMap операторы, в конце собирают все результаты вызовов дооснащения с toList,
Во-первых flatMapIterable вы льете UserDataFollows Список вы получите с первого звонка (getUserFollowing()) в Obsevrable, который испускает несколько элементов из этого списка, затем flatMap создать Observable что делает призыв к модернизации для каждого UserSelfFollows.UserDataFollows объект данных, (это будет происходить параллельно, что кажется больше подходит здесь, но вы также можете использовать concatMap если вы заинтересованы в последовательном выполнении), то собрать все окончательные данные вместе, как список MediaData объекты, вы можете использовать toList

ServiceFactory.createRetrofitService().getUserFollowing(sessionMgr.getAuthToken())
            .flatMapIterable(new Func1<UserSelfFollows, Iterable<?>>() {
                @Override
                public Iterable<?> call(UserSelfFollows userSelfFollows) {
                    return userSelfFollows.userdata;
                }
            })
            .flatMap(new Func1<UserSelfFollows, Observable<Media>>() {
                @Override
                public Observable<Media> call(UserSelfFollows user) {
                    return ServiceFactory.createRetrofitService().getMediaOfUser(user.id, sessionMgr.getAuthToken());
                }
            })
            .toList()
            .subscribe(new Action1<List<Media>>() {
                @Override
                public void call(List<Media> rs) {
                    //do something with the list of media data
                }
            });

Я никогда не использовал оба flatMapIterable или же concatMap, но в качестве альтернативного решения вы могли бы использовать flatMap а также compose оператор:

ServiceFactory.createRetrofitService().getUserFollowing(sessionMgr.getAuthToken())
   .flatMap(list -> Observable.from(list))
   .compose(getComposer())
   .subscribe(mediaData -> mMediaDataList.add(mediaData), throwable -> {}, () -> { // on complete do something with mMediaList});

куда getComposer() возвращает Трансформер UserSelfFollows -> Media.MediaData

protected Observable.Transformer<UserSelfFollows, Media.MediaData> getComposer() {
    return  ;
}

Ответ Йосриза направил меня в правильном направлении. Поэтому, чтобы другие не потянулись за этим, вот ПОЛНОЕ кодовое решение:

ServiceFactory.createRetrofitService().getUserFollowing(sessionMgr.getAuthToken())
                .flatMapIterable(new Func1<UserSelfFollows, Iterable<UserSelfFollows.UserDataFollows>>() {
                    @Override
                    public Iterable< UserSelfFollows.UserDataFollows > call(UserSelfFollows userSelfFollows) {
                        return userSelfFollows.userdata;
                    }
                })
                .flatMap(new Func1<UserSelfFollows.UserDataFollows, Observable<Media>>() {
                    @Override
                    public Observable<Media> call(UserSelfFollows.UserDataFollows user) {
                        return ServiceFactory.createRetrofitService().getMediaOfUser(user.id, sessionMgr.getAuthToken());
                    }
                })
                .toList()
                .subscribeOn(Schedulers.newThread())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Subscriber<List<Media>>() {
                    @Override
                    public final void onCompleted() {

                    }

                    @Override
                    public final void onError(Throwable e) {

                        userMessageHandler.showDialog(mParentActivity, mParentActivity.getString(R.string.error_retrieving_data_title),
                                mParentActivity.getString(R.string.error_self_following_media) + e.getMessage(), 0);
                    }

                    @Override
                    public final void onNext(List<Media> arMedia) {

                        if (arMedia.size() == 0)
                            userMessageHandler.showToast(mParentActivity, mParentActivity.getString(R.string.warn_no_following));
                        else {

                            ArrayList<Media.MediaData> allMedia = new ArrayList<>();
                            for(Media media : arMedia){
                                allMedia.addAll(media.mediaData);
                            }
                            mBinding.gridview.setAdapter(new MediaGridViewAdapter(mParentActivity,FollowingViewModel.this, allMedia));
                        }
                    }
                });
Другие вопросы по тегам