美文网首页
RxJava学习笔记 -- 过滤Observables

RxJava学习笔记 -- 过滤Observables

作者: L_Xian | 来源:发表于2016-11-03 12:00 被阅读119次

    注:本文摘自《RxJava Essentials》翻译中文版电子书

    过滤序列

    使用filter()方法来过滤我们观测序列中不想要的值。只要条件符合filter()函数就会返回true。例如:

    //过滤,只要C开头的
    .filter(new Func1<AppInfo,Boolean>(){
        @Override
        public Boolean call(AppInfo appInfo){
            return appInfo.getName().startsWith("C");
        }
    })
    //过滤null的对象
    .filter(new Func1<AppInfo,Boolean>(){
        @Override
        public Boolean call(AppInfo appInfo){
            return appInfo != null;
        }
    })
    

    获取我们需要的数据

    如果只想取开头或结尾的几个元素,我们可以用take()或takeLast():

    //获取一个可观测序列中的前三个元素
    private void loadList(List<AppInfo> apps) {
        Observable.from(apps)
                .take(3)
                .subscribe(/**代码省略**/);
    }
    //获取最后N个元素
    Observable.from(apps)
            .takeLast(3)
            .subscribe(...);
    

    有且仅有一次

    Distinct

    如果我们想对一个指定的值仅处理一次该怎么办?我们可以对我们的序列使用distinct()
    函数去掉重复的。就像takeLast()一样,distinct()作用于一个完整的序列,然后得到重复的过滤项,它需要记录每一个发射的值。如果你在处理一大堆序列或者大的数据记得关注内存使用情况。
    例子:

    Observable<AppInfo> fullOfDuplicates = Observable.from(apps) .take(3) .repeat(3);
    
    • take():它有一小组的可识别的数据项。
    • repeat():创建一个有重复的大的序列。

    fullOfDuplicates 变量里把我们已安装应用的前三个重复了3次:有9个并且许多重复的。然后,我们使用distinct()函数来去除重复:

    fullOfDuplicates.distinct().subscribe(...);
    
    DistinctUntilsChanged

    引出问题:
    如果在一个可观测序列发射一个不同于之前的一个新值时让我们得到通知这时候该怎么做?我们猜想一下我们观测的温度传感器,每秒发射的室内温度:
    21°...21°...21°...21°...22°...

    每次我们获得一个新值,我们都会更新当前正在显示的温度。我们出于系统资源保护并不想在每次值一样时更新数据。我们想忽略掉重复的值并且在温度确实改变时才想得到通知。

    ditinctUntilChanged()过滤函数能做到这一点。它能轻易的忽略掉所有的重复并且只发射出新的值。

    First and last

    从一个从可观测源序列中创建只发射第一个元素的序列。
    first()方法和last()方法很容易弄明白。它们从Observable中只发射第一个元素或者最后一个元素。

    与first()和last()相似的变量有:firstOrDefault()和lastOrDefault()。这两个函数当可观测序列完成时不再发射任何值时用得上。在这种场景下,如果Observable不再发射任何值时我们可以指定发射一个默认的值。

    Skip and SkipLast

    创建一个不发射前N个元素而是发射它后面的那些数据的序列或者跳过后面N个元素从源序列中发射剩下的其他元素。

    skip()和skipLast()函数与take()和takeLast()相对应。它们用整数N作参数,从本质上来说,它们不让Observable发射前N个或者后N个值。如果我们知道一个序列以没有太多用的“可控”元素开头或结尾时我们可以使用它。

    ElementAt

    如果我们只想要可观测序列发射的第五个元素该怎么办?elementAt()函数仅从一个序列中发射第n个元素然后就完成了。

    如果我们想查找第五个元素但是可观测序列只有三个元素可供发射时该怎么办?我们可以使用elementAtOrDefault()。

    Sampling

    回到那个温度传感器问题,每秒都会发射当前室内的温度。说实话,我们并不认为温度会变化这么快,我们可以使用一个小的发射间隔。在Observable后面加一个sample(),我们将创建一个新的可观测序列,它将在一个指定的时间间隔里由Observable发射最近一次的数值:

    Observable<Integer> sensor = [...]
    sensor.sample(30,TimeUnit.SECONDS)
        .subscribe(...);
    

    上面例子Observable将会观测温度Observable然后每隔30秒就会发射最后一个温度值。sample()支持全部的时间单位:秒,毫秒,天,分等等。
    下图中展示了一个间隔发射字母的Observable如何采样一个发射数字的Observable。Observable的结果将会发射每个已发射字母的最后一组数据:1,4,5.


    sample.png

    如果我们想让它定时发射第一个元素而不是最近的一个元素,我们可以使用throttleFirst()

    Timeout

    假设我们工作的是一个时效性的环境,我们温度传感器每秒都在发射一个温度值。我们想让它每隔两秒至少发射一个,我们可以使用timeout()函数来监听源可观测序列,就是在我们设定的时间间隔内如果没有得到一个值则发射一个错误。我们可以认为timeout()为一个Observable的限时的副本。如果在指定的时间间隔内Observable不发射值的话,它监听的原始的Observable时就会触发onError()函数。

    Subscription subscription = getCurrentTemperature()
        .timeout(2,TimeUnit.SECONDS)
        .subscribe(...);
    

    Debounce

    debounce()函数过滤掉由Observable发射的速率过快的数据;如果在一个指定的时间间隔过去了仍旧没有发射一个,那么它将发射最后的那个。
    就像sample()和timeout()函数一样,debounce()使用TimeUnit对象指定时间间隔。

    相关文章

      网友评论

          本文标题:RxJava学习笔记 -- 过滤Observables

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