【问题标题】:Stitch Data from One Observable into another Observable with RxJava使用 RxJava 将数据从一个 Observable 拼接到另一个 Observable
【发布时间】:2017-03-23 16:05:18
【问题描述】:

我有两个 UserImage 类型的 Observable 流:

final Observable<List<Image>> images = mNetworkingService.getImages(getToken(context));

final Observable<List<User>> users = mNetworkingService.getUsers()
.onErrorReturn(new Func1<Throwable, List<User>>() {
    @Override
    public List<User> call(Throwable throwable) {
        return Collections.emptyList();
    }
});

我想根据 Image 和 User 对象中包含的 userId 将用户的名字和姓氏分配给每个图像对象的 fullName 字段。

这是我目前所拥有的,但不确定 zip 是否是最佳选择。我很接近,但是当我尝试返回图像对象的集合时出现错误,因为它需要一个列表图像,但认为它只是一个图像对象。如果有更好/更清洁的方法来执行此关联/分配,我会感兴趣。

return Observable.zip(images, users, 
new Func2<List<Image>, List<User>, Observable<List<Image>>>() {
    @Override
    public Observable<List<Image>> call(final List<Image> images, List<User> users) {
        for (Image image : images) {
            for (User user : users) {
                if (image.userId.equals(user.userId)) {
                    image.fullName = user.getFullName();
                }
            }
        }
        return Observable.from(images); // Error: Expecting List<Image> but got Image.
    }
}).flatMap(new Func1<Observable<List<Image>>, Observable<List<Image>>>() {
    @Override
    public Observable<List<Image>> call(Observable<List<Image>> it) {
        return it;
    }
});

【问题讨论】:

    标签: rx-java observable rx-android reactivex


    【解决方案1】:

    zip() 如果您想在两个请求都完成后采取行动,那么这两个结果都是正确的选择。

    from()Iterable&lt;T&gt; 作为参数并将其展平为T 的Observable,这意味着它将分别发出每个项目,这意味着 Observable.from(images) 返回 Observable&lt;Image&gt;,而您将 zipper 方法定义为返回 Observable&lt;List&lt;Image&gt;&gt;,因此存在不匹配和编译错误。

    但是,无论如何,您不应该从 zipper 方法返回 Observable,因为 zipper 只是希望您将获得的多个对象转换为单个对象。
    对于 2 项发射的每个“zip”,它将执行拉链,您将获得带有结果压缩对象的 onNext(),但在您的情况下,您将发出 Observable 对象和每个 onNext() ,这可能不是你想要的。

    所以总结起来,你可能想要这样的东西:

    Observable.zip(images, users,
                new Func2<List<Image>, List<User>, List<Image>>() {
                    @Override
                    public List<Image> call(final List<Image> images, List<User> users) {
                        for (Image image : images) {
                            for (User user : users) {
                                if (image.userId.equals(user.userId)) {
                                    image.fullName = user.getFullName();
                                }
                            }
                        }
                        return images; 
                    }
                })
                .subscribe(new Action1<List<Image>>() {
                    @Override
                    public void call(List<Image> images) {
                        //do something with the list of images combined with user data
                    }
                });
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-01-23
      • 1970-01-01
      • 2020-10-10
      • 2017-08-04
      相关资源
      最近更新 更多