美文网首页开源项目学习
RxJava(三) flatMap操作符用法详解

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

作者: Chiclaim | 来源:发表于2017-03-15 10:01 被阅读301次

    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操作符实现获取验证码功能


    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.
    

    官方流程图:

    [图片上传失败...(image-7e2ff3-1516513719869)]

    对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操作符的用法。


    本文的例子放在github上https://github.com/chiclaim/android-sample/tree/master/rxjava

    相关文章

      网友评论

        本文标题: RxJava(三) flatMap操作符用法详解

        本文链接:https://www.haomeiwen.com/subject/fixlnttx.html