原文链接
在第1部分中,我讨论了RxJava的基本结构,并介绍了map()operator。但是,如果你仍然没有意愿去使用RxJava,我可以理解。因为还你没有大量的工作。但是这将迅速改变–RxJava的大部分功能是包含在在框架中的所有Operators。
让我们通过一个例子向你介绍更多的Operators。
假设我这样一个方法:
// Returns a List of website URLs based on a text search Observable<List<String>> query(String text);我想做一个健壮的系统来搜索文本和显示结果。鉴于我们从上一篇文章中知道的,这是可能想出来的:
query("Hello, world!") .subscribe(urls -> { for (String url : urls) { System.out.println(url); } });这个答案令人非常不满意,因为我失去了转换数据流的能力。如果我想修改每个URL,我必须在Subscriber去做,而没有去使用强大的map()处理。
我可以从urls - > urls创建一个map(),但是每个map()调用都会有一个for-each循环。
如下的方法,Observable.from()会遍历集合
Observable.from("url1", "url2", "url3") .subscribe(url -> System.out.println(url));结合上面的需求
query("Hello, world!") .subscribe(urls -> { Observable.from(urls) .subscribe(url -> System.out.println(url)); });确实避免了for-each循环,但是一团糟,有多个嵌套订阅!除了丑陋和难以修改,它也打破了RxJava的一些关键但尚未发现的功能。
Observable.flatMap()获取一个Observable实例,并返回另一个Observable的实例。以下是解决这个问题的方法:
query("Hello, world!") .flatMap(new Func1<List<String>, Observable<String>>() { @Override public Observable<String> call(List<String> urls) { return Observable.from(urls); } }) .subscribe(url -> System.out.println(url));flatMap()很奇怪,对吧?为什么它返回另一个Observable?这里的关键概念是返回的新Observable是被订阅的。它并没有接收List< String > ,它获得一系列由Observable.from()返回的单个字符串。
flatMap()可以返回任何它想要的Observable
假设我有第二种方法:
// Returns the title of a website, or null if 404 Observable<String> getTitle(String URL);现在我要打印每个收到的网站的标题,而不是打印网址。但是有一些问题:我的方法一次只处理一个URL,它不返回一个String,它返回一个发出String的Observable。
使用flatMap(),解决这个问题很容易;在将URL列表拆分为单独的项目后,我可以在flatMap()中为每个URL使用getTitle(),然后再到Subscriber:
query("Hello, world!") .flatMap(urls -> Observable.from(urls)) .flatMap(new Func1<String, Observable<String>>() { @Override public Observable<String> call(String url) { return getTitle(url); } }) .subscribe(title -> System.out.println(title));除了map和flatMap两种operators,还有很多。对上面的操作还可以改进。如果URL是404的时候,getTitle()返回null。
我们不想输出“null”,则可以进行过滤 query("Hello, world!") .flatMap(urls -> Observable.from(urls)) .flatMap(url -> getTitle(url)) .filter(title -> title != null) .subscribe(title -> System.out.println(title));filter 的参数和结果是同一个值,它仅仅对boolean进行判断。
最多显示5个结果,可以这样做 query("Hello, world!") .flatMap(urls -> Observable.from(urls)) .flatMap(url -> getTitle(url)) .filter(title -> title != null) .take(5) .subscribe(title -> System.out.println(title));take()用于指定最多数量。
保存标题到本地 query("Hello, world!") .flatMap(urls -> Observable.from(urls)) .flatMap(url -> getTitle(url)) .filter(title -> title != null) .take(5) .doOnNext(title -> saveTitle(title)) .subscribe(title -> System.out.println(title));doOnNext() 可以添加其他动作,针对每个Item。