RxJava操作符之创建操作符(三)

前言

通过前两篇文章对于RxJava概念,原理及使用的学习,想必各位码友已经基本掌握RxJava的逻辑与功能了,那么从这篇文章开始我们来研究RxJava的各类操作符。

什么是操作符?通过之前的学习,我们发现Observable负责发送事件,Observer负责接收事件,而这个过程中想要对事件数据做出修改就需要交给操作符来负责啦。主流RxJava中操作符主要分为三类:转换操作符,过滤操作符,组合操作符。而我个人将用来创建Observable的操作符归为了一个新类型。本篇我们就来看看常用的创建操作符都有哪些以及如何使用。

创建操作符

Create

上一篇文章的例子中我们已经实践了create操作符如何使用了,这里我们介绍一种便捷的创建Observer的方式。

Observable.create(new Observable.OnSubscribe<String>() {
    @Override
    public void call(Subscriber<? super String> subscriber) {
        for (int i = 0; i < 5; i++) {
            subscriber.onNext("xulei" + i);
        }
        subscriber.onCompleted();
    }
}).subscribe(new Action1<String>() {
    @Override
    public void call(String s) {
        Log.e("rx_test", "create:" + s);
    }
});

subscribe()的入参使用Action1代替原来的Observer,只需重写一个call()方法,等同于原Observer中onNext()方法。如果需要onComplete与onError状态,还可以如下:

.subscribe(new Action1<String>() {
    @Override
    public void call(String s) {
        Log.e("rx_test", "create:" + s);
    }
}, new Action1<Throwable>() {
    @Override
    public void call(Throwable throwable) {
        Log.e("rx_test", "onError:" + throwable.getMessage());
    }
}, new Action0() {
    @Override
    public void call() {
        Log.e("rx_test", "onCompleted");
    }
});

使用new ActionX代替new Observer,代码是不是看起来更加灵活与简洁呢。

Just

just操作符可将某个或某些对象转化为Observable对象,并将其发射出去。参数可为一个或多个数字,字符串。也可为集合,数组,Iterate对象等。

Observable.just(1, 2, 3, 4, 5, 6).subscribe(new Action1<Integer>() {
    @Override
    public void call(Integer integer) {
        Log.e("rx_test", "just:数字:" + integer);
        //数字或者字符串都是单个发射多次
    }
});

List<String> stringList = new ArrayList<>();
stringList.add("Hello");
stringList.add("Ha");
stringList.add("RxJava");
Observable.just(stringList).subscribe(new Action1<List<String>>() {
    @Override
    public void call(List<String> strings) {
        Log.e("rx_test", "just:集合:" + strings.toString());
        //集合或数组是直接发射集合整体,不会拆分
    }
});

输出结果:

just:数字:1
just:数字:2
just:数字:3
just:数字:4
just:数字:5
just:数字:6
just:集合:[Hello, Ha, RxJava]

From

from操作符可将某个对象转化为Observable对象,并且将其发射出去。不同于just,他接收集合或数组,并可将集合数组遍历之后拆分发送。

List<String> stringList = new ArrayList<>();
stringList.add("Hello");
stringList.add("Ha");
stringList.add("RxJava");
Observable.from(stringList).subscribe(new Action1<String>() {
    @Override
    public void call(String s) {
        Log.e("rx_test", "from:" + s);
    }
});

输出结果:

from:Hello
from:Ha
from:RxJava

Range

range(int start, int count)操作符,根据初始值start,与数量count,发射count次以start为基数依次增加的值。

Observable.range(4, 5).subscribe(new Action1<Integer>() {
    @Override
    public void call(Integer integer) {
        Log.e("rx_test", "range:" + integer);
    }
});

输出结果:

range:4
range:5
range:6
range:7
range:8

Defer

defer操作符功能类似于just操作符,不同之处在于defer只有在调用subscribe()方法进行订阅时才创建Observable,而just操作符在初始化Observable就已经创建了,且只创建一个Observable实例。这里我们通过与just对比进行实践。

Action1<String> action1 = new Action1<String>() {
    @Override
    public void call(String s) {
        Log.e("rx_test", s);
    }
};

//defer
Observable<String> deferObservable = Observable.defer(new Func0<Observable<String>>() {
    @Override
    public Observable<String> call() {
        Object o = new Object();
        return Observable.just("defer:hashCode:" + o.hashCode());
    }
});
deferObservable.subscribe(action1);
deferObservable.subscribe(action1);
deferObservable.subscribe(action1);

//just
Observable<String> justObservable = Observable.just("just:hashCode:" + new Object().hashCode());
justObservable.subscribe(action1);
justObservable.subscribe(action1);
justObservable.subscribe(action1);

输出结果:

defer:hashCode:112449879
defer:hashCode:118897732
defer:hashCode:191664429
just:hashCode:121878114
just:hashCode:121878114
just:hashCode:121878114

由输出结果我们可以看出defer每次输出的Observable哈西值是不同的,说明其每subscribe订阅一次都会创建一个新的Observable,从而可保证Observable中的数据都是最新的。而just只有初始化的时候创建一次Observable。

Interval

interval创建操作符,创建一个Observabel并每隔一段时间周期发射一个由0开始增加的数字。
注意:此Observabel是运行在新的线程,所以更新UI需要在主线程中订阅

//每隔100ms发射一个数字,从0自增
Observable.interval(100, TimeUnit.MILLISECONDS) //单位为毫秒
        .observeOn(AndroidSchedulers.mainThread())
        .take(5) //取前5次事件发射,take为过滤操作符,后期会详细讲
        .subscribe(new Action1<Long>() {
            @Override
            public void call(Long aLong) {
                Log.e("rx_test", "interval:" + aLong);
            }
        });

输出结果:

100ms后...
interval:0
100ms后...
interval:1
100ms后...
interval:2
100ms后...
interval:3
100ms后...
interval:4

Timer

timer操作符,创建一个Observable并隔一段时间后发射一个特殊的值,仅发射一次。
注意:此Observabel是运行在新的线程,所以更新UI需要在主线程中订阅

//隔1s后发射一个数字
Observable.timer(1, TimeUnit.SECONDS) //单位为秒
        .observeOn(AndroidSchedulers.mainThread())
        .subscribe(new Action1<Long>() {
            @Override
            public void call(Long aLong) {
                Log.e("rx_test", "timer:" + aLong);
            }
        });

输出结果:

1秒后...
timer:0

Delay

delay操作符,可用于延迟一定时长再发送事件。

//延迟2秒后发射事件
Observable.just(1, 2, 3)
        .delay(2, TimeUnit.SECONDS)
        .subscribe(new Action1<Integer>() {
            @Override
            public void call(Integer integer) {
                Log.e("rx_test", "delay:" + integer);
            }
        });

输出结果:

2秒后...
delay:1
delay:2
delay:3

Repeat

repeat(long count)操作符,将Observable重复发射count次。

//重复发射5次“Sherlock”
Observable.just("Sherlock").repeat(5)
        .subscribe(new Action1<String>() {
            @Override
            public void call(String s) {
                Log.e("rx_test", "repeat:" + s);
            }
     });

输出结果:

repeat:Sherlock
repeat:Sherlock
repeat:Sherlock
repeat:Sherlock
repeat:Sherlock

以上就是常用的一些创建操作符,类似但不常用的还有empty、never、error等等就不一一介绍了,有兴趣的码友可以自行百度。

线程调度Scheduler

RxJava就是用来处理异步任务的,所以就牵扯到生产事件所在线程,处理事件所在线程的问题,下面来看一下RxJava提供的线程调度Scheduler都有哪些。


有了Scheduler,RxJava当然也提供了方法来使用它们。
.subscribeOn()指定被观察者Observable的执行线程。
.observeOn()指定观察者Observer的执行线程。
  
如第一篇文章中的例子:

//获取要查询的小区集合
Observable.from(getCommunitiesFromServer())
        .flatMap(new Func1<Community, Observable<House>>() {
            @Override
            public Observable<House> call(Community community) {
                return Observable.from(community.getHouses());
            }
        })
        .filter(new Func1<House, Boolean>() {
            @Override
            public Boolean call(House house) {
                return house.getPrice() < 200;
            }
        })
        .subscribeOn(Schedulers.io())
        .observeOn(AndroidSchedulers.mainThread())
        .subscribe(new Action1<House>() {
            @Override
            public void call(House house) {
                //显示查询出来的房源信息
                ShowSearchedHousesMessage();
            }
        });

其中.subscribeOn(Schedulers.io())指定了Observable在io线程运行,通常用来执行从服务器获取数据,数据库加载等耗时操作。.observeOn(AndroidSchedulers.mainThread())指定了Observer在Android环境下的UI线程运行,通常用来获取到数据后进行UI刷新的操作。可根据实际需求选择不同线程类型。

总结

到此,本篇关于RxJava的创建类操作符以及线程调度就讲解完毕了,下一篇我们将一起研究RxJava的四类操作符中的转换操作符都有哪些以及如何使用。

技术渣一枚,有写的不对的地方欢迎大神们留言指正,有什么疑惑或者建议也可以在我Github上RxJavaDemo项目Issues中提出,我会及时回复。

附上RxJavaDemo的地址:
RxJavaDemo

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,590评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 86,808评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,151评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,779评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,773评论 5 367
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,656评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,022评论 3 398
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,678评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,038评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,659评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,756评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,411评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,005评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,973评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,053评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,495评论 2 343

推荐阅读更多精彩内容