了解RxJava之操作符(二)
来源:互联网 发布:淘宝琪琪家园怎么样 编辑:程序博客网 时间:2024/06/18 04:05
原文链接:Grokking RxJava, Part 2: Operator, Operator
在第一部分中我浏览了RxJava的基本结构,并且介绍了map操作符。我理解你仍旧没十足的意愿使用RxJava,因为你目前只是了解的一点点。但是看过接下来这么文章就会有所改变,RxJava框架的强大之处在于包含了大量的操作符。
让我通过例子,介绍更多的操作符。
0x00 初始工作
假设有这样一个方法,通过输入内容获取一个URLs列表:
// Returns a List of website URLs based on a text searchObservable<List<String>> query(String text);
我希望构建一个强大的系统,用于查询输入内容并显示查询结果。根据上一篇文章的知识,可能写作这样的代码:
query("Hello, world!") .subscribe(urls -> { for (String url : urls) { System.out.println(url); } });
这个作品完全不尽如人意,以至于失去了修改数据流的能力。如果我希望修改每一个URL,我不得不在Subscriber处理全部的列表。怎么能忘记酷炫的map()操作符呢!
我加入map操作符,但是要处理的还是URLs列表,在内部还是不能摆脱for-each循环。
0x01 一线希望
有个一个方法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循环,但是这份代码是丑陋的,产生了多个嵌套的subscriptions ,除了丑陋和难已修改,还破坏了接下来还每一提到了RxJava的特性。
0x02 改进
救星来了,屏住呼吸:flatMap()
flatMap将一个发射数据的Observable变换为都个Observables,然后将它们发射的数据合并后放在一个单独的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));
使用lambda表达式简化:
query("Hello, world!") .flatMap(urls -> Observable.from(urls)) .subscribe(url -> System.out.println(url));
flatMap()有点怪,对吗?为什么它会返回另一个Observable?这里的关键概念是,新的可观察到的返回是Subscriber要看到的。Subscriber不再收到List,而是收到一系列单独的字符串,就像Observable.from()。
这里对应我来说,比较难以理解。但是一旦顿悟,就飞上云霄。
0x03 还可以更好
不得不强调,flapMap()可以返回任何的Observable。
假设有下面这样的方法:
// Returns the title of a website, or null if 404Observable<String> getTitle(String URL);
现在我不想打印URLs列表,我希望打印一个网站的标题。但是遇到一个问题,这个方法之一次只接受一个URL,并且返回的是发射字符串的Observable,而不是字符串。
通过flatMap(),很容易解决这个问题:
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));
使用lambda表达式简化:
query("Hello, world!") .flatMap(urls -> Observable.from(urls)) .flatMap(url -> getTitle(url)) .subscribe(title -> System.out.println(title));
觉得不可思议,对吗?我将多个独立的Observable组合成一个Observables。太酷了!
不止于此,请注意我组合了两个API的链式调用。当然,我可以组合任意数量的API调用。想想回调地狱吧,现在的逻辑多么简单。
0x04 丰富的操作符
目前,我们只接触两个操作符,还有很多没有接触的。我们怎么样改善我们的代码呢?
如果访问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()不改变发出的数据,只发射通过布尔检查的数据
下面只想要显示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()发出指定数量的事件。(在本例中,如果标题数量少于5个,Observable会提前停止)。
现在我们希望同时在磁盘上保存每一个结果:
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()允许我们在发出事件后添加额外的行为,在本例就是保存标题。
你已经注意到操作数据流是多么的容易!你可以加入更多的操作,程序还不会混乱。
RxJava包含大量的操作符。虽然多的吓人,但是我们值得了解每一个操作符。一旦你知道操作符的使用场景,你就能将操作符转化为真正的力量。
在这些操作符之外,你甚至可以编写自己的操作符。这已经超出本文的范围,基本上只有你想不到的,没有做不到的。
0x05 感觉怎样?
如果这些还不能决心使用RxJava,那你又为什么关心每一个操作符呢?
主要理念3:操作符可以对数据流做任何事。
唯一的限制就在于你自己
你可以通过响应式简化复杂的逻辑。RxJava可以复杂的程序分解为可以组合的片段,这就是响应式编程的魅力。随着你对RxJava的了解,你会为它所折服。
在第三部分,我将介绍RxJava的其他特性,如错误处理和并发性。
另外,想想这多么简化了数据最终的消费形式。在例子最后,我通过两个API调用,修改数据并保存在磁盘。但是Subscriber并不了解这些,它最终只消费Observable。封装简化编程。
- 了解RxJava之操作符(二)
- RxJava 之 操作符
- RxJava系列之二 变换类操作符详解1
- RxJava学习篇之二:操作符的讲解(1)
- Android框架学习之RxJava(二)操作符
- Android框架学习之RxJava(二)操作符
- 深入浅出RxJava(二:操作符)
- 深入浅出RxJava(二:操作符)
- 深入浅出RxJava(二:操作符)
- 深入浅出RxJava二--操作符
- 深入浅出RxJava(二:操作符)
- 深入浅出RxJava(二:操作符)
- 深入浅出RxJava(二:操作符)
- 深入浅出RxJava(二:操作符)
- 深入浅出RxJava(二:操作符)
- 深入浅出RxJava(二:操作符)
- 深入浅出RxJava(二:操作符)
- 深入浅出RxJava(二:操作符)
- HBase集群安装
- 欢迎使用CSDN-markdown编辑器
- adaboost算法
- C++使用hash_map时警告(backward_warning.h:28:)
- 关于Spring-JPA框架下使用多表查询的应用实例记录
- 了解RxJava之操作符(二)
- 从此不求人:自主研发一套PHP前端开发框架(12)
- 【BZOJ1085】[SCOI2005]骑士精神【搜索】【剪枝】
- IOS学习之——UINavigationController 导航控制器
- POJ 2236
- 线程的简单使用
- Toolbar简单封装
- HttpClient网络请求
- 两款WEB防火墙软件介绍