RxJava(三) flatMap 操作符用法详解

RxJava(三) flatMap 操作符用法详解RxJava系列文章目录导读:一、RxJavacreate操作符的用法和源码分析二、RxJavamap操作符用法详解三、RxJavaflatMap操作符用法详解四、RxJavaconcatMap操作符用法详解五、RxJavaonErrorResumeNext操作符实现app与服务器间token机制六、RxJavaretryWhen操作符…

大家好,又见面了,我是你们的朋友全栈君。

RxJava 系列文章目录导读:

一、RxJava create 操作符的用法和源码分析
二、RxJava map 操作符用法详解
三、RxJava flatMap 操作符用法详解
四、RxJava concatMap 操作符用法详解
五、RxJava onErrorResumeNext 操作符实现 app 与服务器间 token 机制
六、RxJava retryWhen 操作符实现错误重试机制
七、RxJava 使用 debounce 操作符优化 app 搜索功能
八、RxJava concat 操作处理多数据源
九、RxJava zip 操作符在 Android 中的实际使用场景
十、RxJava switchIfEmpty 操作符实现 Android 检查本地缓存逻辑判断
十一、RxJava defer 操作符实现代码支持链式调用
十二、combineLatest 操作符的高级使用
十三、RxJava 导致 Fragment Activity 内存泄漏问题
十四、interval、takeWhile 操作符实现获取验证码功能
十五、RxJava 线程的自由切换


flatMap 操作符的作用

官方文档解释:

Returns an Observable that emits items based on applying a function that you supply to each item emitted by the source Observable, where that function returns an Observable, and then merging those resulting Observables and emitting the results of this merger.

官方流程图:

在这里插入图片描述

对 Observable 发射的数据都应用(apply)一个函数,这个函数返回一个 Observable,然后合并这些 Observables,并且发送(emit)合并的结果。 flatMap 和 map 操作符很相像,flatMap 发送的是合并后的 Observables,map 操作符发送的是应用函数后返回的结果集。

flatMap 操作符使用示例

继续 map 操作符的案例

还是以上一篇map操作符的例子吧,如果对 map操作符 不是很了解的,可以看看我之前的文章。

获取主机的IP地址:

   private Observable<String> processUrlIpByOneFlatMap() {
        return Observable.just(
                "http://www.baidu.com/",
                "http://www.google.com/",
                "https://www.bing.com/")
                .flatMap(new Func1<String, Observable<String>>() {
                    @Override
                    public Observable<String> call(String s) {
                        return createIpObservable(s);
                    }
                })
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Action1<String>() {
                    @Override
                    public void call(String s) {
                        printLog(tvLogs, "Consume Data <- ", s);
                    }
                }, new Action1<Throwable>() {
                    @Override
                    public void call(Throwable throwable) {
                        printErrorLog(tvLogs, "throwable call()", throwable.getMessage());
                    }
                });
    }
    
    //根据主机获取ip
    private Observable<String> createIpObservable(final String url) {
        return Observable.create(new Observable.OnSubscribe<String>() {
            @Override
            public void call(Subscriber<? super String> subscriber) {
                try {
                    String ip = getIPByUrl(url);
                    subscriber.onNext(ip);
                    printLog(tvLogs, "Emit Data -> ",url+" : " +ip);
                } catch (MalformedURLException e) {
                    e.printStackTrace();
                    //subscriber.onError(e);
                    subscriber.onNext(null);
                } catch (UnknownHostException e) {
                    e.printStackTrace();
                    //subscriber.onError(e);
                    subscriber.onNext(null);
                }
                subscriber.onCompleted();
            }
        });
    }

输出结果:

Emit Data -> 'http://www.baidu.com/ : 115.239.211.112'
Main Thread:false, Thread Name:RxCachedThreadScheduler-1
Consume Data <- '115.239.211.112'
Main Thread:true, Thread Name:main

Emit Data -> 'http://www.google.com/ : 216.58.199.100'
Main Thread:false, Thread Name:RxCachedThreadScheduler-1
Consume Data <- '216.58.199.100'
Main Thread:true, Thread Name:main

Emit Data -> 'https://www.bing.com/ : 202.89.233.104'
Main Thread:false, Thread Name:RxCachedThreadScheduler-1
Consume Data <- '202.89.233.104'
Main Thread:true, Thread Name:main

flatMap进阶使用

我们从上面的输出结果可以看出,效果和使用 map操作符 的效果是一样。
我们同时也发现线程的名称(Thread Name)都是 RxCachedThreadScheduler-1 ,说明他们是通过一个线程来完成所有的任务的。
如果任务很多,仅仅通过一个线程去做,效率上是不是有点低呢?如果我想使用多个线程来完成这些任务该怎么做呢?
很简单,只需要在创建 Observable 的时候加上subscribeOn(Schedulers.io()) 即可。完整代码如下:

//根据主机获取ip
    private Observable<String> createIpObservable(final String url) {
        return Observable.create(new Observable.OnSubscribe<String>() {
            @Override
            public void call(Subscriber<? super String> subscriber) {
                try {
                    String ip = getIPByUrl(url);
                    subscriber.onNext(ip);
                    printLog(tvLogs, "Emit Data -> ",url+" : " +ip);
                } catch (MalformedURLException e) {
                    e.printStackTrace();
                    //subscriber.onError(e);
                    subscriber.onNext(null);
                } catch (UnknownHostException e) {
                    e.printStackTrace();
                    //subscriber.onError(e);
                    subscriber.onNext(null);
                }
                subscriber.onCompleted();
            }
        })
        .subscribeOn(Schedulers.io());
    }

看下运行效果:

Consume Data <- '202.89.233.103'
Main Thread:true, Thread Name:main
Emit Data -> 'https://www.bing.com/ : 202.89.233.103'
Main Thread:false, Thread Name:RxCachedThreadScheduler-8

Emit Data -> 'http://www.google.com/ : 216.58.203.36'
Main Thread:false, Thread Name:RxCachedThreadScheduler-7
Consume Data <- '216.58.203.36'
Main Thread:true, Thread Name:main
 
Emit Data -> 'http://www.baidu.com/ : 115.239.211.112'
Main Thread:false, Thread Name:RxCachedThreadScheduler-6
Consume Data <- '115.239.211.112'
Main Thread:true, Thread Name:main

从运行可以看出,执行完成任务的不是一个线程了,而是三个不同的线程 RxCachedThreadScheduler-8RxCachedThreadScheduler-7RxCachedThreadScheduler-6

但是发现一个问题,输出的结果的顺序乱了,不是我们输入的 baidu.com、google.com、bing.com 顺序了。

那怎么办呢?

这时候 concatMap 操作符就闪亮登场了,下一篇将介绍 concatMap 操作符的用法。


如果你觉得本文帮助到你,给我个关注和赞呗!

另外,我为 Android 程序员编写了一份:超详细的 Android 程序员所需要的技术栈思维导图

如果有需要可以移步我的 GitHub -> AndroidAll,里面包含了最全的目录和对应知识点链接,帮你扫除 Android 知识点盲区。 由于篇幅原因只展示了 Android 思维导图:
超详细的Android技术栈

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/136177.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • dex文件解析(第三篇)「建议收藏」

    dex文件解析(第三篇)「建议收藏」一张图搞懂dex大图这里图1dex当然也可以通过下面的图12DexFile的文件格式,了解更清楚。DEX文件详解什么是dex文件?如何生成一个dex文件dex文件的作用dex文件格式详解什么是dex文件?dex文件是Android系统中的一种文件,是一种特殊的数据格式,和APK、jar等格式文件类似。能够被DVM识别,加载并执行的文件格式。简单说就

    2022年4月19日
    66
  • 使用LoadRunner进行并发测试、压力测试和负载测试

    使用LoadRunner进行并发测试、压力测试和负载测试版本为LoadRunner12.551.前期准备工作1.1录制脚本并实现参数化和参数关联1.2插入集合点函数lr_rendezvous(“**”);目的是为了让虚拟用户在这个集合点同时向服务器发送请求以实现并发测试2.开始测试2.1压力测试、负载测试和并发测试的区别分析压力测试:系统达到一定饱和度时,系统处理业务的能力负载测试:找到系统最大的负载能力(通过给系统不断的施压达到饱和状态不能加压为止)…

    2022年7月18日
    22
  • eclipse自动补全左边代码_eclipse自动补全返回类型

    eclipse自动补全左边代码_eclipse自动补全返回类型win平台下是:CTRL+1回车MAC下是:command+1回车

    2022年10月13日
    0
  • 大气压力换算公式_气压单位换算表(压力单位换算公式大全)

    大气压力换算公式_气压单位换算表(压力单位换算公式大全)1bar=105Pa,一个标准大气压=1.01325*105Pa;1bar=0.98665标准大气压1巴(bar)=100,000帕(Pa)=10牛顿/平方厘米=0.1MPa是压强的单位,早先气象学中常用毫巴.咱们这教材,气压单位一会是hPa,一会是mb,也不说声是什么意思,网上又。mb=mbar毫巴(=百帕)mbar毫巴(=百帕)hPa百帕1百帕=1毫巴=3/4毫米水银柱.参考资料…

    2022年7月11日
    67
  • vscode创建html文件夹_vscode怎么新建js文件

    vscode创建html文件夹_vscode怎么新建js文件vscode:创建html文件一.创建html文件:1.创建后缀名为.html文档2.创建html的文档结构

    2022年8月22日
    3
  • 图像滤镜艺术—保留细节的磨皮滤镜之PS实现

    图像滤镜艺术—保留细节的磨皮滤镜之PS实现本文介绍了一种极为简单的PS磨皮实现过程,这个过程将有对应的程序实现,效果也将一模一样,这里跟大家分享一下!

    2022年7月22日
    8

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号