简体   繁体   English

在返回订阅服务器之前,如何拦截可观察对象并在RxJava中修改它?

[英]How can I intercept an observable object and modify it in RxJava before returning to Subscriber?

I'm currently trying to hit a service and get returned a list of objects, before it gets returned to the subscriber, I want to make another synchronous call for each object in the list to make another service call to set a missing field. 我正在尝试命中一个服务并返回一个对象列表,在它返回给订阅者之前,我想对列表中的每个对象进行另一个同步调用,以进行另一个服务调用来设置一个丢失的字段。 I'm successfully having all calls being made, but the object returned in the subscriber has this field I need to have set to null. 我已成功完成所有调用,但订阅者返回的对象具有此字段,我需要将其设置为null。 Here is an example of my code: 这是我的代码示例:

Example Service: 示例服务:

rx.Observable<List<ExampleObject>> getExampleObject();
rx.Observable<MissingObject> getMissingObjectByFoo(@Path("foo") String foo);

Example Class: 示例类:

public class ExampleObject {
    String foo;
    MissingObject bar;

    public String getFoo() {
        return this.foo;
    }

    public void setFoo(String value) {
        this.foo = value;
    }

    public MissingObject getBar() {
        return this.bar;
    }

    public void setBar(MissingObject value) {
        this.bar = value;
    }
}

Example Implementation: 示例实施:

mService.getExampleObject().flatMap(new Func1<List<ExampleObject>, Observable<?>>() {
            @Override
            public Observable<List<ExampleObject>> call(List<ExampleObject> exampleObjects) {
                for (ExampleObject entry : exampleObjects) {
                    String foo = entry.getFoo();
                    mService.getMissingObjectByFoo(foo)
                            .subscribeOn(mScheduler.backgroundThread())
                            .observeOn(mScheduler.mainThread())
                            .subscribe(new Subscriber<MissingObject>() {
                        @Override
                        public void onCompleted() {

                        }

                        @Override
                        public void onError(Throwable e) {

                        }

                        @Override
                        public void onNext(MissingObject missingObject) {
                            entry.setBar(missingObject);
                        }
                    });
                }
                return Observable.just(exampleObjects);
            };

Because your intermediary call to update the entry is asynchronous, I don't think you can stick to using a List<ExampleObject> , but should instead manipulate ExampleObject directly from the Observable : 因为您更新条目的中间调用是异步的,所以我认为您不能坚持使用List<ExampleObject> ,而应该直接从Observable操作ExampleObject

mService.getExampleObject()
    // Spread the list
    .flatMap(list -> Observable.from(list))
    // Update your object
    // Here we zip the object with the missing object,
    // so that when the missing object is obtained,
    // we update the entry and emit it.
    .flatMap(entry -> Observable.zip(
           Observable.just(entry), 
           mDocsService.getMissingObjectByFoo(entry.getFoo()), 
           (entry, missingObject) -> {
               entry.setBar(missingObject);
               return entry;
           })
    )
    // if you really want a map after all
    .toList();

Side note: 边注:

You can skip the zip if you are fine with having the function in the map depend on an external variable (the entry). 如果您在map中的功能取决于外部变量(条目),那么您可以跳过该zip。 That's something I try to avoid, but here it is anyway: 这是我试图避免的,但无论如何它在这里:

    .flatMap(entry -> mDocsService.getMissingObjectByFoo(entry.getFoo())
                                  .map(missingObject -> {
                                      entry.setBar(missingObject);
                                      return entry;
                                   })
    )

You're looking for the zip operator, as described here: Zip Operator . 您正在寻找zip运算符,如下所述: Zip运算符 I think you want to flatmap to a zip of all of your calls, so, something like this: 我想你想把你的所有电话的拉链平面映射到一个拉链,所以,像这样:

    mService.getExampleObject().flatMap(new Func1<List<ExampleObject>, Observable<ExampleObject>>() {
        @Override
        public Observable<List<ExampleObject>> call(List<ExampleObject> exampleObjects) {
            List<Observable<ExampleObject>> allTheObservables = new ArrayList<Observable<ExampleObject>>();
            for (ExampleObject entry : exampleObjects) {
                allTheObservables.add(mService.getMissingObjectByFoo(foo).map(new Func1<MissingObject, ExampleObject>() {
                    @Override
                    public ExampleObject call(MissingObject missingObject) {
                        return entry.setBar(missingObject);
                    }
                }));
            }
            return Observable.zip(allTheObservables, new FuncN<ExampleObject>() {
                @Override
                public ExampleObject call(ExampleObject... args) {
                    return Arrays.asList(args);
                }
            });
        }
    });

and in case that doesn't work, or there are syntax issues, here's a concrete example, using the github api: 如果不起作用,或者存在语法问题,这是一个具体的例子,使用github api:

    service.getContributorsObservable("square", "dagger")
        .flatMap(new Func1<List<Contributor>, Observable<List<String>>>() {
            @Override
            public Observable<List<String>> call(List<Contributor> contributors) {
                List<Observable<String>> allTheObservables = new ArrayList<>(contributors.size());
                for (final Contributor contributor : contributors) {
                    allTheObservables.add(service.getContributorsObservable(contributor.login).map(new Func1<User, String>() {

                        @Override
                        public String call(User user) {
                            return contributor.login + " is " + user.name;
                        }
                    }));
                }
                return Observable.zip(allTheObservables, new FuncN<List<String>>() {
                    @Override
                    public List<String> call(Object... args) {
                        return Arrays.asList((String[]) args);
                    }
                });
            }
        });

Keep in mind that this will make n+1 network calls, 1 for the list of ExampleObject s, and then 1 per ExampleObject in that list. 请记住,这将进行n + 1个网络调用,1表示ExampleObject列表,然后是该列表中的每个ExampleObject 1个。 If it is at all possible, I strongly suggest that you speak with the maintainer of the API to get the information lookup taken care of on the API side. 如果可能我强烈建议你使用API的维护者,以获得在API方面的信息查找照顾说话。 Just know that this is going to use some bandwidth! 只知道这将使用一些带宽!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 在RxJava中调用Observable的任何订户回调之前,请执行操作 - Do an action before any subscriber callback of an Observable is called in RxJava 我如何在 Observable RxJava 中测试参数 - How I can test arguments in Observable RxJava 如何在两个Observable(RxJava)之间重用订阅服务器 - How can I reuse a Subscriber between two Observables (RxJava) RxJava Observable和Subscriber用于跳过异常? - RxJava Observable and Subscriber for skipping exception? RxJava:如何重置长时间运行的热可观察链? - RxJava: How can I reset a long running hot observable chain? 我怎样才能停止观察一个 observable 而不在 RxJava2 中处理它? - How can I stop observing an observable without disposing it in RxJava2? 如何返回一个RxJava Observable,保证不会抛出OnErrorNotImplementedException? - How can I return an RxJava Observable which is guaranteed not to throw OnErrorNotImplementedException? RxJava:如何从observable中提取对象? - RxJava: How to extract object from observable? 如何在RxJava中的一个对象中合并两个对象? - How can I combine two object in one of the object in RxJava? 如何实现与INotifyPropertyChanged等效的RxJava来生成Observable数据模型? - How can I implement the RxJava equivalent of INotifyPropertyChanged to make an Observable data model?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM