Java的RxJava库操作符的用法及实例讲解
操作符就是为了解决对Observable对象的变换的问题,操作符用于在Observable和最终的Subscriber之间修改Observable发出的事件。RxJava提供了很多很有用的操作符。 Observable.just("Hello,world!") .map(new Func1<String,String>() { @Override public String call(String s) { return s + " -Dan"; } }) .subscribe(s -> System.out.println(s)); 使用lambda可以简化为 Observable.just("Hello,world!") .map(s -> s + " -Dan") .subscribe(s -> System.out.println(s)); 是不是很酷?map()操作符就是用于变换Observable对象的,map操作符返回一个Observable对象,这样就可以实现链式调用,在一个Observable对象上多次使用map操作符,最终将最简洁的数据传递给Subscriber对象。
Observable.just("Hello,world!") .map(new Func1<String,Integer>() { @Override public Integer call(String s) { return s.hashCode(); } }) .subscribe(i -> System.out.println(Integer.toString(i))); 很有趣吧?我们初始的Observable返回的是字符串,最终的Subscriber收到的却是Integer,当然使用lambda可以进一步简化代码: Observable.just("Hello,world!") .map(s -> s.hashCode()) .subscribe(i -> System.out.println(Integer.toString(i))); 前面说过,Subscriber做的事情越少越好,我们再增加一个map操作符 Observable.just("Hello,world!") .map(s -> s.hashCode()) .map(i -> Integer.toString(i)) .subscribe(s -> System.out.println(s)); 不服? 实例 Observable<List<String>> query(String text); 现在我希望构建一个健壮系统,它可以查询字符串并且显示结果。根据上一篇blog的内容,我们可能会写出下面的代码: query("Hello,world!") .subscribe(urls -> { for (String url : urls) { System.out.println(url); } }); 这种代码当然是不能容忍的,因为上面的代码使我们丧失了变化数据流的能力。一旦我们想要更改每一个URL,只能在Subscriber中来做。我们竟然没有使用如此酷的map()操作符!!! 当然,我可以使用map操作符,map的输入是urls列表,处理的时候还是要for each遍历,一样很蛋疼。 万幸,还有Observable.from()方法,它接收一个集合作为输入,然后每次输出一个元素给subscriber: 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)); });
2.改进 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呢?理解flatMap的关键点在于,flatMap输出的新的Observable正是我们在Subscriber想要接收的。现在Subscriber不再收到List<String>,而是收到一些列单个的字符串,就像Observable.from()的输出一样。 这部分也是我当初学RxJava的时候最难理解的部分,一旦我突然领悟了,RxJava的很多疑问也就一并解决了。 3.还可以更好 // 返回网站的标题,如果404了就返回null Observable<String> getTitle(String URL);
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)); 4.使用lambda: query("Hello,world!") .flatMap(urls -> Observable.from(urls)) .flatMap(url -> getTitle(url)) .subscribe(title -> System.out.println(title)); 是不是感觉很不可思议?我竟然能将多个独立的返回Observable对象的方法组合在一起!帅呆了! 5.丰富的操作符 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()输出最多指定数量的结果。 如果我们想在打印之前,把每个标题保存到磁盘: 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包含了大量的操作符。操作符的数量是有点吓人,但是很值得你去挨个看一下,这样你可以知道有哪些操作符可以使用。弄懂这些操作符可能会花一些时间,但是一旦弄懂了,你就完全掌握了RxJava的威力。 你甚至可以编写自定义的操作符!这篇blog不打算将自定义操作符,如果你想的话,清自行Google吧。 感觉如何? 因为操作符可以让你对数据流做任何操作。 将一系列的操作符链接起来就可以完成复杂的逻辑。代码被分解成一系列可以组合的片段。这就是响应式函数编程的魅力。用的越多,就会越多的改变你的编程思维。 另外,RxJava也使我们处理数据的方式变得更简单。在最后一个例子里,我们调用了两个API,对API返回的数据进行了处理,然后保存到磁盘。但是我们的Subscriber并不知道这些,它只是认为自己在接收一个Observable<String>对象。良好的封装性也带来了编码的便利!
您可能感兴趣的文章:
(编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |