如何在rxJava中返回值

15

我刚接触rxJava,它让我感到晕头转向。基本上,我正在使用retrofit从youtube api中提取数据,这会返回一个Observable,然后使用youtubeDataMapper将其映射为包含字符串videoID的Youtube Pojo对象。所以我的问题是,如何使此方法返回该字符串而不是Completable?

这是我的方法:

@Override
  public Completable downloadVideoUrl(String query) {

    addSubscription(youtubeApi.getYoutubeId(query, Constants.youtubeApi)
                              .map(youtubeDataMapper::map)
                              .subscribeOn(subscribeScheduler)
                              .observeOn(observeScheduler)
                              .subscribe());
    return Completable.complete();
}
2个回答

11

您有两个选择:

  1. 将您的 downloadVideoUrl 方法返回类型从 Completable 改为 Observable:

    首选方式:

    @Override
    public Completable downloadVideoUrl(String query) {
        return youtubeApi.getYoutubeId(query, Constants.youtubeApi)
                .map(youtubeDataMapper::map)
                .subscribeOn(subscribeScheduler)
                .observeOn(observeScheduler);
    }
    

    注意这里缺少subscribe操作符。

    然后无论您想在哪里获取videoId:

    downloadVideoUrl(query)
        .subscribe(new Subscriber<String>() {
                    @Override
                    public void onCompleted() {
    
                    }
    
                    @Override
                    public void onError(Throwable e) {
    
                    }
    
                    @Override
                    public void onNext(String videoId) {
                        // do whatever you want with videoId
                    }
                });
    
  2. 使用 toBlocking().first()

    这种方法不太推荐,因为它会阻塞当前线程,直到 Observable 完成

  3. @Override
    public String downloadVideoUrl(String query) {
        return youtubeApi.getYoutubeId(query, Constants.youtubeApi)
                .map(youtubeDataMapper::map)
                .subscribeOn(subscribeScheduler)
                .observeOn(observeScheduler)
                .toBlocking().first();
    }
    

0
首先,最好让Retrofit返回Single而不是Observable,因为您期望单个服务器响应(而不是一系列响应)。
其次,Completable.complete()是一个不做任何事情的Completable工厂方法。所以你在这里不需要它。
关于String videoID,这取决于您打算如何使用它。此外,我不知道您的.addSubscription()正在做什么。
我建议像以下这样做:

class YourClass {

    private final CompositeSubscription compositeSubscription = new CompositeSubscription();
    // you must call compositeSubscription.clear() either in class .finalize() or on some UI lifecycle event

    void yourMethod() {
        final Single videoID = youtubeApi.getYoutubeId(query, Constants.youtubeApi)
                .map(youtubeDataMapper::map)
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread());
        final Subscription subscription = videoID.subscribe(new SingleSubscriber() {                    
                    @Overridepublic void onSuccess(String value) {
                        // TODO: do whatever with the value
                    }
                    @Override
                    public void onError(Throwable error) {                         
                        // TODO: log and/or display error
                    }
                });
       compositeSubscription.add(subscription);
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接