我刚刚开始使用RxJava。我一直在尝试构建一个数据管道,从不同的源下载大量数据,并以并发方式将数据插入数据库。
我的基本管道表格如下所示:
Observable.range(1, 5)
.concatMap((i) -> {
return Observable.range(i, 2);
})
.concatMap((i) -> {
return Observable.range(i, 2);
})
.subscribe((i) -> { System.out.println(i); }, System.out::println,() -> { System.out.println("Complete"); });
每当我调用observeOn而不是运行并打印出上面打印出来的所有数字时,都没有打印出来。为什么是这样?我希望下一个concatMap和subscribe也会使用计算调度程序。代码发布在下面。
Observable.range(1, 5)
.concatMap((i) -> {
return Observable.range(i, 2);
})
.observeOn(Schedulers.computation())
.concatMap((i) -> {
return Observable.range(i, 2);
})
.subscribe((i) -> { System.out.println(i); }, System.out::println,() -> { System.out.println("Complete"); });
答案 0 :(得分:2)
这是一个猜测,因为你没有提供上下文,但是如果你正在更改线程,你必须阻止,因为主要没有被阻止,你可能在另一个调度程序有机会运行之前终止:
Observable.range(1, 5)
.concatMap((i) -> {
return Observable.range(i, 2);
})
.observeOn(Schedulers.computation())
.concatMap((i) -> {
return Observable.range(i, 2);
})
.subscribe((i) -> { System.out.println(i); }, System.out::println,() -> { System.out.println("Complete"); });
// block to let other schedulers finish
Thread.sleep(3000);
答案 1 :(得分:0)
在阅读您的评论以获得更多上下文之后,我假设您想要获取ID列表(项目摘要),然后为每个返回的ID提出一个额外请求以获取每个项目'详细信息,然后对结果(项目)做一些事情。
考虑到您已经拥有构建和触发请求的方法,请返回Observable
。您可以包装http相关代码并将Observable推迟,或者从Future
创建一个Observable,以防您的http库返回Future
。
// you have this available
Observable<Summary> = querySummary(summaryId);
Observable<Item> = queryItem(itemId);
我没有运行以下任何代码,因此请将其作为指导。你可以从:
开始Observable<Item> itemsObservable = querySummary(summaryId)
.flatMap(summary -> {
return Observable.from(summary.getItemsIdsList());
})
.map(itemId -> {
return queryItem(itemId);
});
您正在查询摘要,然后使用flatMap
运算符发出单个返回的ID。然后你可以map
每个id来发送一个请求。最后,您可以订阅itemsObservable
以让各个Item
对象流动。
如果要在订阅前保存数据库中的项目,可以在最后doOnNext
的尾部插入map
并保存每个项目。如果要对每个项目中的值求和,或进行任何聚合,可以使用reduce
。依此类推。按照它的方式,最后只有一个.subscribe()
,这个代码在主线程中运行(如果你的http库没有任何花哨的线程池功能)。
itemsObservable.doOnNext(item -> {
// do something in whatever thread it might be running
}).subscribe();
如果要触发摘要请求并异步等待,请触发项目&#39;请求同时在新项ID到达时,您可以像添加.observeOn(Schedulers.io())
一样。
Observable<Item> itemsObservable = querySummary(summaryId)
.observeOn(Schedulers.io()) // from here, continue in the background
.flatMap(summary -> { // ...
请注意,您告诉Observable链在另一个线程中执行并忘记它。在同样的情况下,这正是你想要的。但是如果你从一个普通的public static void main()
方法运行它作为你的程序体,你的程序将在后台执行结束之前关闭,这是预期的。如果你直接处理对线程对象的引用,你应该自己负责join()
线程,使主程序等待它们。
由于反应流意味着隐藏线程复杂性,您只需要&#34;说&#34;你想在聚会结束时聚在一起。在这种情况下,要将执行返回到主线程,您可以插入.toBlocking()
或.toList()
。然后,您可以安全地在当前主题的订阅的onNext
处获得结果。
itemsObservable
.toBlocking()
.subscribe(item -> {
// blocking the main thread
// do something on each item
});
或..
itemsObservable
.toList()
.subscribe(itemsList -> {
// blocking the main thread
// do something with the whole list at once
});
有许多不同的方法可以组成Observable,创建一个或多个流,合并它们,异步运行它们。因此,它可以满足您的需求。
我希望它有所帮助!