美文网首页
RxJava(四) concatMap操作符用法详解

RxJava(四) concatMap操作符用法详解

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

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


    concatMap操作符的作用

    concatMap操作符和flatMap操作符非常类似。如果对 flatMap操作符 不是很了解可以点击链接去看看我的上一篇博文。下面是concatMap操作符的流程图:

    [图片上传失败...(image-d04959-1516513687646)]

    concatMap和flatMap最大的区别是concatMap发射的数据集是有序的,flatMap发射的数据集是无序的。

    concatMap操作符的用法示例

    通过上一篇对flatMap的介绍,我们的例子程序输出的结果是无序的。现在把代码中的flatMap换成concatMap:

    Observable.from(Arrays.asList(
                "http://www.baidu.com/",
                "http://www.google.com/",
                "https://www.bing.com/"))
                .concatMap(new Func1<String, Observable<String>>() {
                        @Override
                        public Observable<String> call(String s) {
                            return createIpObservableMultiThread(s);
                        }
                    })
                .observeOn(AndroidSchedulers.mainThread());
    
    
        // 获取ip
        private synchronized Observable<String> createIpObservableMultiThread(final String url) {
            return Observable
                    .create(new Observable.OnSubscribe<String>() {
                        @Override
                        public void call(Subscriber<? super String> subscriber) {
                            try {
                                String ip = getIPByUrl(url);
                                printLog(tvLogs, "Emit Data -> ", url + "->" + ip);
                                subscriber.onNext(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());
        }
    
    

    输出结果:

    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.221.132'Main Thread:false, Thread Name:RxCachedThreadScheduler-3
    Emit Data -> 'https://www.bing.com/->202.89.233.104' Main Thread:false, Thread Name:RxCachedThreadScheduler-2
    Consume Data <- '216.58.221.132' Main Thread:true, Thread Name:main
    Consume Data <- '202.89.233.104' Main Thread:true, Thread Name:main 
    

    输出的结果始终都是baidu/google/bing, 使用的线程都是不同的线程。这也就解决了上篇博客提出的问题:既要是多个线程完成任务,又要保持任务的顺序

    但是出现了一个奇怪的问题:上篇博客我们使用flatMap在多个线程完成任务,有时候顺序是乱的。但是concatMap一开始也是使用一个线程来完成任务,只有先调用flatMap多线程完成任务,然后再调用concatMap才会有多线程。
    实验结果表明:如果RxJava有了多个线程,concatMap才会使用多个线程,如果Rxjava里只有一个缓存的线程,concatMap只是用一个线程来执行任务,尽管加上了.subscribeOn(Schedulers.io())代码。然而如果是flatMap加上.subscribeOn(Schedulers.io())代码,每次调用都是多个线程的。这也是flatMap和concatMap的又一个区别。


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

    相关文章

      网友评论

          本文标题:RxJava(四) concatMap操作符用法详解

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