欢迎转载,转载请标明出处:

http://blog.csdn.net/johnny901114/article/details/51568562

本文出自:【余志强的博客】

一、concat操作符概述

从concatMap操作我们知道,concat操作符肯定也是有序的,而concat操作符是接收若干个Observables,发射数据是有序的,不会交叉。

下面看看官方文档和流程图的说明:

Returns an Observable that emits the items emitted by three Observables,
one after the other, without interleaving them.

二、使用示例

示例一

下面使用concat操作符 来实现个多数据源的例子,比如一个商品详情需要展示商品的信息、艺术家信息、与该商品类似的商品,可能需要访问三个接口。这个时候就可以使用concat操作符

卖家信息

    private Observable<Object> sellerInfo = Observable.create(new Observable.OnSubscribe<Object>() {
        @Override
        public void call(Subscriber<? super Object> subscriber) {
            Seller d = goodsApi.getSeller();
            if (d != null) {
                subscriber.onNext(d);
            }
            subscriber.onCompleted();
        }
    }).subscribeOn(Schedulers.io());

商品信息

    private Observable<Object> goodsInfo = Observable.create(new Observable.OnSubscribe<Object>() {
        @Override
        public void call(Subscriber<? super Object> subscriber) {
            Goods d = goodsApi.getGoodInfo();
            if (d != null) {
                subscriber.onNext(d);
            }
            subscriber.onCompleted();
        }
    }).subscribeOn(Schedulers.io());

类似作品推荐

    private Observable<Object> relateGoods = Observable.create(new Observable.OnSubscribe<Object>() {
        @Override
        public void call(Subscriber<? super Object> subscriber) {
            List<Goods> d = goodsApi.getRelateGoods();
            if (d != null) {
                subscriber.onNext(d);
            }
            subscriber.onCompleted();
        }
    }).subscribeOn(Schedulers.io());
Observable.concat(sellerInfo, goodsInfo, relateGoods)
                        .observeOn(AndroidSchedulers.mainThread())
                        .subscribe(new Action1<Object>() {
                            @Override
                            public void call(Object s) {
                                printLog(tvLogs, "Getting data from ", s);
                                //push data to ui
                            }
                        }, new Action1<Throwable>() {
                            @Override
                            public void call(Throwable throwable) {
                                throwable.printStackTrace();
                                printLog(tvLogs, "Error: ", throwable.getMessage());
                            }
                        });

为什么泛型去设置成Object呢,因为Observable.concat只接受相同泛型的参数。

也许会有人问后去商品信息的时候没办法传递参数啊(比如商品ID), 在外面包一层方法即可,方法参数为goodID。

示例二

使用 concat操作符 对缓存进行检查,如:内存缓存、本地缓存、网络,那一层有数据立即返回。

使用一个数组来表示三个数据源:

String data[] = {null, null, "network"};
//String data[] = {null, "disk","network"};
//String data[] = {"memory", null,"network"};
//String data[] = {"memory", "disk",null};
//String data[] = {"memory", "disk","network"};

内存缓存

  private Observable<String> memorySource = Observable.create(new Observable.OnSubscribe<String>() {
        @Override
        public void call(Subscriber<? super String> subscriber) {
            String d = data[0];
            printLog(tvLogs, "", "----start check memory data. value is null? " + (d == null));
            if (d != null) {
                subscriber.onNext(d);
            }
            subscriber.onCompleted();
        }
    });

本地缓存


    private Observable<String> diskSource = Observable.create(new Observable.OnSubscribe<String>() {
        @Override
        public void call(Subscriber<? super String> subscriber) {
            String d = data[1];
            printLog(tvLogs, "", "----start check disk data. value is null? " + (d == null));
            if (d != null) {
                subscriber.onNext(d);
            }
            subscriber.onCompleted();
        }
    }).subscribeOn(Schedulers.io());

网络

    private Observable<String> networkSource = Observable.create(new Observable.OnSubscribe<String>() {
        @Override
        public void call(Subscriber<? super String> subscriber) {
            String d = data[2];
            printLog(tvLogs, "", "----start check network data. value is null? " + (d == null));
            if (d != null) {
                subscriber.onNext(d);
            }
            subscriber.onCompleted();
        }
    }).subscribeOn(Schedulers.io());

从例子1我们知道,concat会三个数据源都会请求的。如何使得哪层有数据就用哪层的,之后就不走后面的逻辑了。

可以配合first()操作符来实现这样的效果。

Observable.concat(memorySource, diskSource, networkSource)
                        .first()
                        .observeOn(AndroidSchedulers.mainThread())
                        .subscribe(new Action1<String>() {
                            @Override
                            public void call(String s) {
                                printLog(tvLogs, "Getting data from ", s);
                            }
                        }, new Action1<Throwable>() {
                            @Override
                            public void call(Throwable throwable) {
                                throwable.printStackTrace();
                                printLog(tvLogs, "Error: ", throwable.getMessage());
                            }
                        });

需要注意的是如果memorySource, diskSource, networkSource返回的都null,那么会报一个异常:

java.util.NoSuchElementException: Sequence contains no elements……

可以使用takeFirst操作,即使都没有数据,也不会报异常。

Observable.concat(memorySource, diskSource, networkSource)
                        //first()-> if no data from observables will cause exception :
                        //java.util.NoSuchElementException: Sequence contains no elements
                        //takeFirst -> no exception
                        .takeFirst(new Func1<String, Boolean>() {
                            @Override
                            public Boolean call(String s) {
                                return s != null;
                            }
                        })
                        .observeOn(AndroidSchedulers.mainThread())
                        .subscribe(new Action1<String>() {
                            @Override
                            public void call(String s) {
                                printLog(tvLogs, "Getting data from ", s);
                            }
                        }, new Action1<Throwable>() {
                            @Override
                            public void call(Throwable throwable) {
                                throwable.printStackTrace();
                                printLog(tvLogs, "Error: ", throwable.getMessage());
                            }
                        });

除了通过concat操作符来实现缓存逻辑,也可使用switchIfEmpty ,详细可以查看我的博客:

http://blog.csdn.net/johnny901114/article/details/52585912


github源码下载

RxJava(八)concat符操作处理多数据源的更多相关文章

  1. .NET LINQ 限定符操作

    限定符操作      限定符运算返回一个 Boolean 值,该值指示序列中是否有一些元素满足条件或是否所有元素都满足条件. 方法 方法名 说明 C# 查询表达式语法 Visual Basic 查询表 ...

  2. TP5常用命令符操作

    ThinkPHP5常用命令符操作   1. 模块自动生成指令:   默认会读取应用目录application下面的build.php作为自动   生成的定义文件,如果你的定义文件位置不同,则需要使用 ...

  3. C#路径的八种相关操作,判断字符串是否为路径等

    原文:C#路径的八种相关操作,判断字符串是否为路径等 1.判定一个给定的C#路径是否有效,合法 通过Path.GetInvalidPathChars或Path.GetInvalidFileNameCh ...

  4. selenium webdriver学习(八)------------如何操作select下拉框(转)

    selenium webdriver学习(八)------------如何操作select下拉框 博客分类: Selenium-webdriver   下面我们来看一下selenium webdriv ...

  5. RxJava的concat操作符

    更多文章请点击:http://77blogs.com/?p=170 转载请标明出处:https://www.cnblogs.com/tangZH/p/12088332.html,http://77bl ...

  6. RxJava操作符(05-结合操作)

    转载请标明出处: http://blog.csdn.net/xmxkf/article/details/51656736 本文出自:[openXu的博客] 目录: CombineLatest Join ...

  7. Django(十八)Model操作补充

    参考博客:http://www.cnblogs.com/wupeiqi/articles/6216618.html 1. 创建类 class UserInfo(model.Model): age = ...

  8. 八.python文件操作

    一,初识文件操作. 引子: 现在这个世界上,如果可以操作文件的所有软件都消失了,比如word,wps等等,此时你的朋友通过qq给你发过来一个文件,文件名是:美女模特空姐护士联系方式.txt,在座的所有 ...

  9. jQuery-1.9.1源码分析系列(八) 属性操作

    jQuery的属性操作主要包括 jQuery.fn.val jQuery.fn.attr jQuery.fn.removeAttr jQuery.fn.prop jQuery.fn.removePro ...

随机推荐

  1. [WC 2010]重建计划

    Description Input 第一行包含一个正整数N,表示X国的城市个数. 第二行包含两个正整数L和U,表示政策要求的第一期重建方案中修建道路数的上下限 接下来的N-1行描述重建小组的原有方案, ...

  2. [Codeforces]853E - Lada Malina

    题目大意:给出平面上$n$个带权点$f_{i}$,再给出$k$个向量$v_{i}$,每次询问给出一个点$p$和一个值$t$,求能满足$f_{i}+\sum w_{j}v_{j}=p(-t<=w_ ...

  3. remove、erase

    remove: remove不是真正的删除,删除后数量并没有变化. 它接收一对迭代器,而不是一个容器,所以不知道它作用于哪个容器. 而且没有办法从一个迭代器获取对应于它的容器 实现 remove会用需 ...

  4. 【网络流】【BZOJ1006】【SCOI2007】蜥蜴

    学弟@lher在周末训练赛中出的题目的原题(这个人拿省选题来当作提高组模拟,太丧了...) 题意简析:看题目:) 解题思路:题目显然是最大流. 首先拆点将点权变为边权,然后按照题意对于所有有跳板的点向 ...

  5. 例10-7 uva10820(欧拉)

    题意:输入n,要求满足1≤x,y≤n,且x,y互素的个数. 若输入2,则答案3为(1,1),(1,2),(2,1);所以欧拉函数求出所有数的phi值,除了1之外都加上phi值的2倍即可 通过推导: p ...

  6. [bzoj4824][Cqoi2017]老C的键盘

    来自FallDream的博客,未经允许,请勿转载,谢谢. 老 C 是个程序员.     作为一个优秀的程序员,老 C 拥有一个别具一格的键盘,据说这样可以大幅提升写程序的速度,还能让写出来的程序在某种 ...

  7. 用js来实现那些数据结构11(字典)

    我们这篇文章来说说Map这种数据结构如何用js来实现,其实它和集合(Set)极为类似,只不过Map是[键,值]的形式存储元素,通过键来查询值,Map用于保存具有映射关系的数据,Map里保存着两组数据: ...

  8. Python3 运算符

    装载自:https://www.cnblogs.com/cisum/p/8064222.html Python3 运算符 什么是运算符? 本章节主要说明Python的运算符.举个简单的例子 4 +5 ...

  9. Spring学习笔记6——注解方式测试

    需要下载junit-4.12.jar和hamcrest-all-1.3.jar,将下载好的包导入到项目当中. 修改TestSpring, 并运行1. @RunWith(SpringJUnit4Clas ...

  10. Unity脚本自动添加注释脚本及排版格式

    Unity脚本自动添加注释脚本及头部注释排版格式 公司开发项目,需要声明版权所有,,,,标注公司名,作者,时间,项目名称及描述等等. 自己总结实现的现成脚本及头部注释排版文本,添加到模版即可. 文件不 ...