如何在完成之前使用一个rxjava observable?

时间:2016-03-10 08:32:58

标签: android rx-java

我有两个RxJava Observable,我从第一个observable获得一个arraylist,然后用它从另一个observable中获取数据。

Observable<KarobarTvVod> observable1 = youtubeDataHelper.getTVData();
    observable1.subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .unsubscribeOn(Schedulers.io())
            .subscribe(new Subscriber<KarobarTvVod>() {
                @Override
                public void onCompleted() {

                }

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

                @Override
                public void onNext(KarobarTvVod karobarTvVod) {
                    Log.d(TAG, "onNext: size" + karobarTvVod.getEtag());
                    tvObjArrayList = new ArrayList<TVObj>();
                    for (int i = 0; i < karobarTvVod.getItems().size(); i++) {
                        TVObj tvObj = new TVObj();
                        tvObj.setVideoDate(karobarTvVod.getItems().get(i).getSnippet().getPublishedAt());
                        tvObj.setVideoIcon(karobarTvVod.getItems().get(i).getSnippet().getThumbnails().getHigh().getUrl());
                        tvObj.setVideoTitle(karobarTvVod.getItems().get(i).getSnippet().getTitle());
                        tvObj.setVideoID(karobarTvVod.getItems().get(i).getId().getVideoId());
                        tvObjArrayList.add(tvObj);
                    }


                }
            });



    Observable<YoutubeViews> observable2 = youtubeDataHelper.getTVDataViews(tvObjArrayList);
    observable2.subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .unsubscribeOn(Schedulers.io())
            .subscribe(new Subscriber<YoutubeViews>() {
                @Override
                public void onCompleted() {

                }

                @Override
                public void onError(Throwable e) {
                    Log.d(TAG, "onError: in 2nd obs");
                    e.printStackTrace();
                }

                @Override
                public void onNext(YoutubeViews youtubeViews) {
                    Log.d(TAG, "onNext: views" + youtubeViews.getEtag());
                    viewsList = new ArrayList<String>();
                    for (int i = 0; i < youtubeViews.getItems().size(); i++) {

                        viewsList.add(youtubeViews.getItems().get(i).getStatistics().getViewCount());
                    }
                    tvView.displayList(tvObjArrayList, viewsList);
                }
            });

这只是示例代码,我需要在从第一个Observable填充到第二个Observable时传递tvObjArrayList,这样做的最佳做法是什么?而且我在第一个Observable中使用for循环,是否有更好的方法来使用rxjava实现它?感谢

4 个答案:

答案 0 :(得分:5)

您应该使用flatMap运算符。它不会比那更容易。

Observable<KarobarTvVod> observable1 = youtubeDataHelper.getTVData();
observable1.subscribeOn(Schedulers.io())
        .observeOn(AndroidSchedulers.mainThread())
        .unsubscribeOn(Schedulers.io())
        .flatMap(new Func1<KarobarTvVod, Observable<YoutubeViews>>() {
            @Override
            public Observable<YoutubeViews> call(KarobarTvVod karobarTvVod) {
                Log.d(TAG, "onNext: size" + karobarTvVod.getEtag());
                tvObjArrayList = new ArrayList<TVObj>();
                for (int i = 0; i < karobarTvVod.getItems().size(); i++) {
                    TVObj tvObj = new TVObj();
                    tvObj.setVideoDate(karobarTvVod.getItems().get(i).getSnippet().getPublishedAt());
                    tvObj.setVideoIcon(karobarTvVod.getItems().get(i).getSnippet().getThumbnails().getHigh().getUrl());
                    tvObj.setVideoTitle(karobarTvVod.getItems().get(i).getSnippet().getTitle());
                    tvObj.setVideoID(karobarTvVod.getItems().get(i).getId().getVideoId());
                    tvObjArrayList.add(tvObj);
                }
                return youtubeDataHelper.getTVDataViews(tvObjArrayList);
            }
        }).subscribe(new Subscriber<YoutubeViews>() {
            @Override
            public void onCompleted() {

            }

            @Override
            public void onError(Throwable e) {
                Log.d(TAG, "onError: in 1st or 2nd obs");
                e.printStackTrace();
            }

            @Override
            public void onNext(YoutubeViews youtubeViews) {
                Log.d(TAG, "onNext: views" + youtubeViews.getEtag());
                viewsList = new ArrayList<String>();
                for (int i = 0; i < youtubeViews.getItems().size(); i++) {

                    viewsList.add(youtubeViews.getItems().get(i).getStatistics().getViewCount());
                }
                tvView.displayList(tvObjArrayList, viewsList);
            }
        });

答案 1 :(得分:1)

您可以使用运算符

toList().flatMap()

对于Observable A,在flatMap函数中,对Observable B起作用。

例如:

observableA
    .toList()
    .flatMap(observableB.subscribe())
    .subscribe()

答案 2 :(得分:1)

我认为getTVDatagetTVDataViews每个都会发出一个项目,而不是调用onComplete。如果是,则比以下示例有效。没有loop,只有纯rx:)

//getTVData should emit one item and then call obComplete
//otherwise toList() will wait forever
service.getTVData()
        .flatMap(karobarTvVod -> Observable.from(karobarTvVod.getItems()))
        .map(item -> {
            TVObj tvObj = new TVObj();
            //set other fields
            //by the way, I recommend you to use immutable objects
            return tvObj;
        })
        .toList()
        //here we have List<TVObj>
        .flatMap(
                objs -> {
                    //getTVDataViews should emit one item and then call onComplete
                    //otherwise toList will wait forever
                    return service.getTVDataViews(objs)
                            .flatMap(youtubeViews -> Observable.from(youtubeViews.getItems()))
                            .map(integer -> integer.toString())
                            //after that we will have List<String>
                            .toList();
                },
                //a function that combines one item emitted by each of the source and collection Observables 
                // and returns an item to be emitted by the resulting Observable
                new Func2<List<TVObj>,List<String>,Pair<List<TVObj>,List<String>>>() {
                    @Override
                    public Pair<List<TVObj>, List<String>> call(List<TVObj> objs, List<String> strings) {
                        return new Pair(objs, strings);
                    }
                })
        .subscribe(pair -> tvView.displayList(pair.first, pair.second));

PS。虽然这种方法更简洁,但我认为loop用于创建项目的list效率更高。

答案 3 :(得分:0)

您需要在第一个

的onComplete中订阅第二个observable
    Observable<KarobarTvVod> observable1 = youtubeDataHelper.getTVData();
    Observable<YoutubeViews> observable2 = youtubeDataHelper.getTVDataViews(tvObjArrayList);

    observable1.subscribeOn(Schedulers.io())
        .observeOn(AndroidSchedulers.mainThread())
        .unsubscribeOn(Schedulers.io())
        .subscribe(new Subscriber<KarobarTvVod>() {
            @Override
            public void onCompleted() {
                 observable2.subscribeOn(Schedulers.io())
           .observeOn(AndroidSchedulers.mainThread())
           .unsubscribeOn(Schedulers.io())
           .subscribe(new Subscriber<YoutubeViews>() {
                   @Override
                   public void onCompleted() {

                   }

                   @Override
                   public void onError(Throwable e) {
                       Log.d(TAG, "onError: in 2nd obs");
                       e.printStackTrace();
                   }

                   @Override
                   public void onNext(YoutubeViews youtubeViews) {
                       Log.d(TAG, "onNext: views" + youtubeViews.getEtag());
                       viewsList = new ArrayList<String>();
                       for (int i = 0; i < youtubeViews.getItems().size(); i++) {

                           viewsList.add(youtubeViews.getItems().get(i).getStatistics().getViewCount       ());
                       }
                       tvView.displayList(tvObjArrayList, viewsList);
                   }
               });
            }

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

            @Override
            public void onNext(KarobarTvVod karobarTvVod) {
                Log.d(TAG, "onNext: size" + karobarTvVod.getEtag());
                tvObjArrayList = new ArrayList<TVObj>();
                for (int i = 0; i < karobarTvVod.getItems().size(); i++) {
                    TVObj tvObj = new TVObj();
                    tvObj.setVideoDate(karobarTvVod.getItems().get(i).getSnippet().getPublishedAt());
                    tvObj.setVideoIcon(karobarTvVod.getItems().get(i).getSnippet().getThumbnails().getHigh().getUrl());
                    tvObj.setVideoTitle(karobarTvVod.getItems().get(i).getSnippet().getTitle());
                    tvObj.setVideoID(karobarTvVod.getItems().get(i).getId().getVideoId());
                    tvObjArrayList.add(tvObj);
                }


            }
        });

当然为了使这段代码更具可读性,我会在onComplete方法上使用Consumer函数作为observable2.subsriberOn