如何在RxJava中执行递归可观察调用?

我对RxJava (以及一般的反应范式) 都很陌生 ,所以请耐心等待。

假设我有这个News和这个嵌套的Comment数据结构:

 public class News { public int id; public int[] commentIds; //only top level comments public News(int id, int[] commentIds) { this.id = id; this.commentIds = commentIds; } } public class Comment { public int id; public int parentId; //ID of parent News or parent comment public int[] childIds; public Comment(int id, int parentId, int[] childIds) { this.id = id; this.parentId = parentId; this.childIds = childIds; } } 

并假设我有这个API端点:

 getComments(int commentId) //return Observable for Comment with ID commentId 

现在,让我们假设:

 getComments(1); //will return Comment(1, 99, [3,4]) getComments(2); //will return Comment(2, 99, [5,6]) getComments(3); //will return Comment(3, 1, []) getComments(4); //will return Comment(4, 1, []) getComments(5); //will return Comment(5, 2, []) getComments(6); //will return Comment(6, 2, []) 

**

现在,如果我有News n = News(99, [1,2]) ,我如何让它的所有孩子递归评论? 即获得ID [1,2,3,4,5,6]的评论?

**

我搜索并偶然发现了这个问题: https : //jkschneider.github.io/blog/2014/recursive-observables-with-rxjava.html

这是递归函数:

 public class FileRecursion { static Observable listFiles(File f) { if(f.isDirectory()) return Observable.from(f.listFiles()).flatMap(FileRecursion::listFiles); return Observable.just(f); } public static void main(String[] args) { Observable.just(new File("/Users/joschneider/Desktop")) .flatMap(FileRecursion::listFiles) .subscribe(f -> System.out.println(f.getAbsolutePath())); } } 

它显示了如何进行递归可观察调用的示例,但内部函数( f.listFiles() )是一个阻塞操作(不返回另一个Observable)。 在我的例子中,内部函数( getComments )是一个非阻塞函数,它返回另一个Observables。 我怎么做?

任何帮助都感激不尽。

这几乎与文章中描述的内容相同:

 Observable getInnerComments(Comment comment) { if (comment.childIds.length > 0) return Observable.merge( Observable.just(comment), Observable.from(comment.childIds) .flatMap(id -> getComments(id)) .flatMap(this::getInnerComments)); return Observable.just(comment); } public static void main(String[] args) { getComments(1) .flatMap(this::getInnerComments) .subscribe(c -> System.out.println(comment.toString())); } 

我从id = 1的注释开始,然后将其传递给getInnerComments()getInnerComments()检查注释是否有子项。 如果是,则迭代每个子ID( Observable#from )并使用getComments(int) API加载每个子ID。 然后将每个子getInnerComments()传递给getInnerComments()以执行相同的过程。 如果注释没有子项,则立即使用Observable#just返回。

这是伪代码,它没有经过测试,但你应该明白这个想法。


下面是如何获取所有注释然后将它们聚合到一个List的示例。

 getNews(99) .flatMap(news -> Observable.from(news.commentIds)) .flatMap(commentId -> getComments(commentId)) .flatMap(comment -> getInnerComments(comment)) .toList() .subscribe(commentList -> { });