RxJava操作符(二)Transforming Observables
在上一篇文章中,我们了解了如何创建Observable,仅仅创建一个Observable可能无法满足一些复杂的场景,所以我们很可能需要将创建的Observable安装某种规则转化一下来发射数据。在这篇文章里我们来了解一下如何来转化Observable一、Buffer
顾名思义,Buffer操作符所要做的事情就是将数据安装规定的大小做一下缓存,然后将缓存的数据作为一个集合发射出去。如下图所示,第一张示例图中我们指定buffer的大小为3,收集到3个数据后就发射出去,第二张图中我们加入了一个skip参数用来指定每次发射一个集合需要跳过几个数据,图中如何指定count为2,skip为3,就会每3个数据发射一个包含两个数据的集合,如果count==skip的话,我们就会发现其等效于第一种情况了。


buffer不仅仅可以通过数量规则来缓存,还可以通过时间等规则来缓存,如规定3秒钟缓存发射一次等,见下面代码,我们创建了两个Observable,并使用buffer对其进行转化,第一个通过数量来缓存,第二个通过时间来缓存。
<ol style="margin:0 1px 0 0px;padding-left:40px;" start="1" class="dp-css"><li>private Observable<List<Integer>> bufferObserver() {<br /></li><li>return Observable.just(1, 2, 3, 4, 5, 6, 7, 8, 9).buffer(2, 3);<br /></li><li>}<br /></li><li><br /></li><li>private Observable<List<Long>> bufferTimeObserver() {<br /></li><li>return Observable.interval(1, TimeUnit.SECONDS).buffer(3, TimeUnit.SECONDS).observeOn(AndroidSchedulers.mainThread());<br /></li><li>}</li></ol>对其进行订阅
<ol style="margin:0 1px 0 0px;padding-left:40px;" start="1" class="dp-css"><li>mLButton.setText("buffer");<br /></li><li>mLButton.setOnClickListener(e -> bufferObserver().subscribe(i -> log("buffer:" + i)));<br /></li><li>mRButton.setText("bufferTime");<br /></li><li>mRButton.setOnClickListener(e -> bufferTimeObserver().subscribe(i -> log("bufferTime:" + i)));</li></ol>
运行结果如下,可以看到第一个Observable会每隔3个数字发射出前两个数字;第二个Observable会每隔3秒钟输出2~4个数字。

二、FlatMap
FlatMap是一个用处多多的操作符,可以将要数据根据你想要的规则进行转化后再发射出去。其原理就是将这个Observable转化为多个以原Observable发射的数据作为源数据的Observable,然后再将这多个Observable发射的数据整合发射出来,需要注意的是最后的顺序可能会交错地发射出来,如果对顺序有严格的要求的话可以使用concatmap操作符。FlatMapIterable和FlatMap基相同,不同之处为其转化的多个Observable是使用Iterable作为源数据的。

下面我们分别使用FlatMap和FlatMapIterable创建并转化两个Observable。
<ol style="margin:0 1px 0 0px;padding-left:40px;" start="1" class="dp-css"><li>private Observable<String> flatMapObserver() {<br /></li><li>return Observable.just(1, 2, 3, 4, 5, 6, 7, 8, 9).flatMap(integer -> Observable.just("flat map:" + integer));<br /></li><li>}<br /></li><li><br /></li><li>private Observable<? extends Integer> flatMapIterableObserver() {<br /></li><li>return Observable.just(1, 2, 3, 4, 5, 6, 7, 8, 9)<br /></li><li>.flatMapIterable(<br /></li><li>integer -> {<br /></li><li>ArrayList<Integer> s = new ArrayList<>();<br /></li><li>for (int i = 0; i < integer; i++) {<br /></li><li>s.add(integer);<br /></li><li>}<br /></li><li>return s;<br /></li><li>}<br /></li><li>);<br /></li><li>}</li></ol>分别对其进行订阅
<ol style="margin:0 1px 0 0px;padding-left:40px;" start="1" class="dp-css"><li>mLButton.setText("flatMap");<br /></li><li>mLButton.setOnClickListener(e -> flatMapObserver().subscribe(i -> log(i)));<br /></li><li>mRButton.setText("flatMapIterable");<br /></li><li>mRButton.setOnClickListener(e -> flatMapIterableObserver().subscribe(i -> log("flatMapIterable:" + i)));</li></ol>
运行后的结果如下所示,第一个操作符将发射的数据都加上了个flat map的字符串前缀,第二个将数据做了扩展,会输出n个n数字。

三、GroupBy
GroupBy操作符将原始Observable发射的数据按照key来拆分成一些小的Observable,然后这些小的Observable分别发射其所包含的的数据,类似于sql里面的groupBy。
在使用中,我们需要提供一个生成key的规则,所有key相同的数据会包含在同一个小的Observable种。另外我们还可以提供一个函数来对这些数据进行转化,有点类似于集成了flatMap。

下面创建两个经过groupBy转化的Observable对象,第一个按照奇数偶数分组,第二个分组后将数字加上一个字符串前缀
<ol style="margin:0 1px 0 0px;padding-left:40px;" start="1" class="dp-css"><li>mLButton.setText("groupBy");<br /></li><li>mLButton.setOnClickListener(e -> groupByObserver().subscribe(new Subscriber<GroupedObservable<Integer, Integer>>() {<br /></li><li>@Override<br /></li><li>public void onCompleted() {<br /></li><li><br /></li><li>}<br /></li><li><br /></li><li>@Override<br /></li><li>public void onError(Throwable e) {<br /></li><li><br /></li><li>}<br /></li><li><br /></li><li>@Override<br /></li><li>public void onNext(GroupedObservable<Integer, Integer> groupedObservable) {<br /></li><li>groupedObservable.count().subscribe(integer -> log("key" + groupedObservable.getKey() + " contains:" + integer + " numbers"));<br /></li><li>}<br /></li><li>}));<br /></li><li>mRButton.setText("groupByKeyValue");<br /></li><li>mRButton.setOnClickListener(e -> groupByKeyValueObserver().subscribe(new Subscriber<GroupedObservable<Integer, String>>() {<br /></li><li>@Override<br /></li><li>public void onCompleted() {<br /></li><li><br /></li><li>}<br /></li><li><br /></li><li>@Override<br /></li><li>public void onError(Throwable e) {<br /></li><li><br /></li><li>}<br /></li><li><br /></li><li>@Override<br /></li><li>public void onNext(GroupedObservable<Integer, String> integerIntegerGroupedObservable) {<br /></li><li>if (integerIntegerGroupedObservable.getKey() == 0) {<br /></li><li>integerIntegerGroupedObservable.subscribe(integer -> log(integer));<br /></li><li>}<br /></li><li>}<br /></li><li>}));<br /></li><li>}</li></ol>
运行结果如下,我们拿到想要的结果。

四、Map、Cast
Map操作符的功能类似于FlatMap,不同之处在于它对数据的转化是直接进行的,而FlatMap需要通过一些中间的Observables来进行。

Cast将Observable发射的数据强制转化为另外一种类型,属于Map的一种具体的实现

下面我们创建两个经过map和cast转化的Observable对象
<ol style="margin:0 1px 0 0px;padding-left:40px;" start="1" class="dp-css"><li>private Observable<Integer> mapObserver() {<br /></li><li>return Observable.just(1, 2, 3, 4, 5, 6, 7, 8, 9).map(integer -> integer * 10);<br /></li><li>}<br /></li><li><br /></li><li>private Observable<Dog> castObserver() {<br /></li><li>return Observable.just(getAnimal())<br /></li><li>.cast(Dog.class);<br /></li><li>}<br /></li><li><br /></li><li>Animal getAnimal() {<br /></li><li>return new Dog();<br /></li><li>}<br /></li><li><br /></li><li>class Animal {<br /></li><li>protected String name = "Animal";<br /></li><li><br /></li><li>Animal() {<br /></li><li>log("create " + name);<br /></li><li>}<br /></li><li><br /></li><li>String getName() {<br /></li><li>return name;<br /></li><li>}<br /></li><li>}<br /></li><li><br /></li><li>class Dog extends Animal {<br /></li><li>Dog() {<br /></li><li>name = getClass().getSimpleName();<br /></li><li>log("create " + name);<br /></li><li>}<br /></li><li><br /></li><li>}</li></ol>对其进行注册
<ol style="margin:0 1px 0 0px;padding-left:40px;" start="1" class="dp-css"><li>mLButton.setText("Map");<br /></li><li>mLButton.setOnClickListener(e -> mapObserver().subscribe(i -> log("Map:" + i)));<br /></li><li>mRButton.setText("Cast");<br /></li><li>mRButton.setOnClickListener(e -> castObserver().subscribe(i -> log("Cast:" + i.getName())));</li></ol>运行后得到结果如下。可以看到,map操作符将数据都乘以10后再发射出来,cast操作符将Animal类型的对象强制转化为Dog类型的对象。另外我们还可以验证一下一个知识点,有继承的情况下创建对象会首先调用父类的构造方法哦。

五、Scan
Scan操作符对一个序列的数据应用一个函数,并将这个函数的结果发射出去作为下个数据应用这个函数时候的第一个参数使用,有点类似于递归操作

下面我们通过一个存放10个2的list创建一个Observable对象并使用scan对其进行转化,转化的函数就是计算的结果乘以下一个数。
<ol style="margin:0 1px 0 0px;padding-left:40px;" start="1" class="dp-css"><li>private Observable<Integer> scanObserver() {<br /></li><li>return Observable.from(list).scan((x, y) -> x * y).observeOn(AndroidSchedulers.mainThread());<br /></li><li>}</li></ol>对其进行订阅
<ol style="margin:0 1px 0 0px;padding-left:40px;" start="1" class="dp-css"><li>mLButton.setText("scan");<br /></li><li>mLButton.setOnClickListener(e -> scanObserver().subscribe(i -> log("scan:" + i)));</li></ol>得到结果如下,可以看到,我们输出了2的n次方。

六、Window
Window操作符类似于我们前面讲过的buffer,不同之处在于window发射的是一些小的Observable对象,由这些小的Observable对象来发射内部包含的数据。同buffer一样,window不仅可以通过数目来分组还可以通过时间等规则来分组

下面我们创建两个Observable对象分别使用window的数目和时间规则来进行分组。
<ol style="margin:0 1px 0 0px;padding-left:40px;" start="1" class="dp-css"><li>private Observable<Observable<Integer>> windowCountObserver() {<br /></li><li>return Observable.just(1, 2, 3, 4, 5, 6, 7, 8, 9).window(3);<br /></li><li>}<br /></li><li><br /></li><li>private Observable<Observable<Long>> wondowTimeObserver() {<br /></li><li>return Observable.interval(1000, TimeUnit.MILLISECONDS)<br /></li><li>.window(3000, TimeUnit.MILLISECONDS)<br /></li><li>.observeOn(AndroidSchedulers.mainThread());<br /></li><li>}</li></ol>分别对其订阅
<ol style="margin:0 1px 0 0px;padding-left:40px;" start="1" class="dp-css"><li>mLButton.setText("window");<br /></li><li>mLButton.setOnClickListener(e -> windowCountObserver().subscribe(i -> {<br /></li><li>log(i);<br /></li><li>i.subscribe((j -> log("window:" + j)));<br /></li><li>}));<br /></li><li>mRButton.setText("Time");<br /></li><li>mRButton.setOnClickListener(e -> wondowTimeObserver().subscribe(i -> {<br /></li><li>log(i);<br /></li><li>i.observeOn(AndroidSchedulers.mainThread()).subscribe((j -> log("wondowTime:" + j)));<br /></li><li>}));</li></ol>运行结果如下,可以看到第一个Observable对象没次发射出一个包含3个数据的小Observable,第二个Observable对象每隔3秒钟发射出一个包含2~4个数据的Observable对象

Transforming操作符是Rxjava强大之处的重要体现,要灵活使用Rxjava掌握Transforming操作符是必不可少的。
本文的demo程序见github:https://github.com/Chaoba/RxJavaDemo

根据美国司法部的解释,蓝色警报旨在提供关于可能对执法人员构成直接和紧急威胁的个人的重要信息。这种警报的目的是及时通知公众,并让他们了解与这些罪犯相关的潜在危险。通过这种主动的方式,蓝色警报有助于增强社区的安全意识,促使人们采取必要的预防措施以保护自己和周围的人。这种警报系统的建立旨在提高对潜在威胁的警觉性,并加强执法机构与公众之间的沟通,以共尽管这些紧急通知对我们社会至关重要,但有时可能会对日常生活造成干扰,尤其是在午夜或重要活动时收到通知时。为了确保安全,我们建议您保持这些通知功能开启,但如果

Android中的轮询是一项关键技术,它允许应用程序定期从服务器或数据源检索和更新信息。通过实施轮询,开发人员可以确保实时数据同步并向用户提供最新的内容。它涉及定期向服务器或数据源发送请求并获取最新信息。Android提供了定时器、线程、后台服务等多种机制来高效地完成轮询。这使开发人员能够设计与远程数据源保持同步的响应式动态应用程序。本文探讨了如何在Android中实现轮询。它涵盖了实现此功能所涉及的关键注意事项和步骤。轮询定期检查更新并从服务器或源检索数据的过程在Android中称为轮询。通过

为了提升用户体验并防止数据或进度丢失,Android应用程序开发者必须避免意外退出。他们可以通过加入“再次按返回退出”功能来实现这一点,该功能要求用户在特定时间内连续按两次返回按钮才能退出应用程序。这种实现显著提升了用户参与度和满意度,确保他们不会意外丢失任何重要信息Thisguideexaminesthepracticalstepstoadd"PressBackAgaintoExit"capabilityinAndroid.Itpresentsasystematicguid

1.java复杂类如果有什么地方不懂,请看:JAVA总纲或者构造方法这里贴代码,很简单没有难度。2.smali代码我们要把java代码转为smali代码,可以参考java转smali我们还是分模块来看。2.1第一个模块——信息模块这个模块就是基本信息,说明了类名等,知道就好对分析帮助不大。2.2第二个模块——构造方法我们来一句一句解析,如果有之前解析重复的地方就不再重复了。但是会提供链接。.methodpublicconstructor(Ljava/lang/String;I)V这一句话分为.m

如何将WhatsApp聊天从Android转移到iPhone?你已经拿到了新的iPhone15,并且你正在从Android跳跃?如果是这种情况,您可能还对将WhatsApp从Android转移到iPhone感到好奇。但是,老实说,这有点棘手,因为Android和iPhone的操作系统不兼容。但不要失去希望。这不是什么不可能完成的任务。让我们在本文中讨论几种将WhatsApp从Android转移到iPhone15的方法。因此,坚持到最后以彻底学习解决方案。如何在不删除数据的情况下将WhatsApp

原因:1、安卓系统上设置了一个JAVA虚拟机来支持Java应用程序的运行,而这种虚拟机对硬件的消耗是非常大的;2、手机生产厂商对安卓系统的定制与开发,增加了安卓系统的负担,拖慢其运行速度影响其流畅性;3、应用软件太臃肿,同质化严重,在一定程度上拖慢安卓手机的运行速度。

1.启动ida端口监听1.1启动Android_server服务1.2端口转发1.3软件进入调试模式2.ida下断2.1attach附加进程2.2断三项2.3选择进程2.4打开Modules搜索artPS:小知识Android4.4版本之前系统函数在libdvm.soAndroid5.0之后系统函数在libart.so2.5打开Openmemory()函数在libart.so中搜索Openmemory函数并且跟进去。PS:小知识一般来说,系统dex都会在这个函数中进行加载,但是会出现一个问题,后

1.自动化测试自动化测试主要包括几个部分,UI功能的自动化测试、接口的自动化测试、其他专项的自动化测试。1.1UI功能自动化测试UI功能的自动化测试,也就是大家常说的自动化测试,主要是基于UI界面进行的自动化测试,通过脚本实现UI功能的点击,替代人工进行自动化测试。这个测试的优势在于对高度重复的界面特性功能测试的测试人力进行有效的释放,利用脚本的执行,实现功能的快速高效回归。但这种测试的不足之处也是显而易见的,主要包括维护成本高,易发生误判,兼容性不足等。因为是基于界面操作,界面的稳定程度便成了


热AI工具

Undresser.AI Undress
人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover
用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

AI Hentai Generator
免费生成ai无尽的。

热门文章

热工具

PhpStorm Mac 版本
最新(2018.2.1 )专业的PHP集成开发工具

Dreamweaver Mac版
视觉化网页开发工具

SecLists
SecLists是最终安全测试人员的伙伴。它是一个包含各种类型列表的集合,这些列表在安全评估过程中经常使用,都在一个地方。SecLists通过方便地提供安全测试人员可能需要的所有列表,帮助提高安全测试的效率和生产力。列表类型包括用户名、密码、URL、模糊测试有效载荷、敏感数据模式、Web shell等等。测试人员只需将此存储库拉到新的测试机上,他就可以访问到所需的每种类型的列表。

DVWA
Damn Vulnerable Web App (DVWA) 是一个PHP/MySQL的Web应用程序,非常容易受到攻击。它的主要目标是成为安全专业人员在合法环境中测试自己的技能和工具的辅助工具,帮助Web开发人员更好地理解保护Web应用程序的过程,并帮助教师/学生在课堂环境中教授/学习Web应用程序安全。DVWA的目标是通过简单直接的界面练习一些最常见的Web漏洞,难度各不相同。请注意,该软件中

MinGW - 适用于 Windows 的极简 GNU
这个项目正在迁移到osdn.net/projects/mingw的过程中,你可以继续在那里关注我们。MinGW:GNU编译器集合(GCC)的本地Windows移植版本,可自由分发的导入库和用于构建本地Windows应用程序的头文件;包括对MSVC运行时的扩展,以支持C99功能。MinGW的所有软件都可以在64位Windows平台上运行。