RxJava——响应式编程魅力《续》

RxJava——响应式编程续

继续来学习我们的RxJava,接着前面一篇的内容,接下来我们要开始看什么是Observer和Operator。

Observer

任何订阅了Observable的东西,都可以称之为Observer;只要Observable发送了数据,所有订阅了它的Observer都会收到通知。

在我们举的会议的例子中,所有坐在那里听发言者讲话的人都是Observer。每当发言人在台上说出某些内容的时候,所有与会者都可以倾听并做出反应。

Observer有三种可以接受的事务类型:

  • onNext(T) —— 当源Observable发出指定项(类型为T)时,它将会被调用。如果源Observable有多个要发出的项,它将多次被调用。
  • onCompleted() —— 当源Observable发出了它的所有items之后,它会被调用。它表明Observable已经被成功完成,
  • onError(Throwable) —— 当源Observab了发生错误的时候,它将会被调用。这也是一个结束事件,它提供一个Throwable,里面包含了错误的详细信息。

代码时间

DisposableObserver<Movie> disposable = movieObservable
.subscribeWith(new DisposableObserver<Movie>(){
    @Override
    public void onNext(Movie movie){
        // 获取movie
    }
    
    @Override
    public void onComplete(){
        //通知事件结束
    }
    
    @Override
    public void onError(Throwable e){
        // 处理错误
    }
})

每次observable提取Movie对象时,都会调用onNext(Movie)方法。它可以从网络,数据库,文件或任何其他来源(这并不重要)获取。重要的是订阅它的Observer将始终收到流中发生的事件的通知。

因此,如果您的数据存储中有10部电影,那么将使用10个电影对象调用onNext()方法10次。操作成功后,将调用onComplete()方法,但如果失败,将使用相应的错误对象调用onError()方法。

什么是Dispose?

上面的代码里面还有一样东西没有弄清楚,那就是DisposableObserver。

DisposableObserver只是一个Observer,可以在实现Disposable接口时进行处理。每当Observer订阅一个Observable时,就会在它们之间形成一个连接,当不需要时,它实际上需要被清除(或终止),否则会导致资源泄漏。

你还可以使用CompositeDisposable来添加所有disposable,并立即清除所有一次性用品。

Operator

接下来,又是RxJava的一个重头戏了。

RxJava 的强大之处就在于它提供了大量的操作符,操作符基本上是纯函数,用来转换或者修改可观察的数据流。

还是回到一开始的会议例子上,假设一个新的发言人要上台开始用日语发言,但是坐在那里的与会人员都只会中文,这时候我们怎么处理呢?

这时候我们就需要一个Tanslater出现,将发言者的每一句话都翻译成所有与会人员都能理解的有意义的内容。

具体的在RxJava中来看看吧。

  • filter() —— 用于过滤源Observer发出的项,并创建一个新的Observable,其中只包含符合条件的项。

假设,我们的电影Observable可以给出不同评分的电影,但我们只想展示5星的电影。

movieObservable.filter(new Predicate<Moview>){
    @Override
    public boolean test(@NonNull Movie movie) throws Exception {
        return movie.getRating() == 5;
    }
}

我们可以直接使用lambda表达式来写:

movieObservable.filter(movie -> movie.getRating() == 5);
  • map() —— 用于将Observable发出的项转换为完全不同的项,并创建一个包含这些修改项的新Observable

继续假设,如果我们要求显示的电影概要不能超过500个字符,那么我们可以这样来做。

Observable<Movie> movieObservable = getMovieFromDatabase();
movieObservable.map(new Function<Movie, Movie> {
    @Override
    public Movie apply(@NonNull Movie movie) throws Exception {
        return new Movie(StringUtils.truncate(movie.getSynopsis(),500))
    }
})

同样的,我们可以用lambda表达式进行简化:

movieObservable.map(movie -> new Movie(truncate(movi.getSynopsis(), 500)));
  • skip() —— 用于从源Observable的开头跳过一些项,并创建一个没有这些项的新Observble。

假设,我们知道我们的电影的Observable在流的开头发出一个虚拟的Movie对象用于测试,不应该向用户显示。

movieObservable.skip(1);
  • concat() —— 用于依次连接多个Observable。

还是电影的例子,我们有两个数据源获取电影——数据库和网络,我们想要先显示数据库中的电影之后再显示网络请求的电影。

Observable<Movie> database = getMoviesFromDatabase();
Observable<Movie> network = getMoviesFromNetwork();

Observable<Movie> resultObservable = Observable.concat(database, network);

这些运算符方法的返回类型也是Observable,这就意味着我们可以把这一个个多个运算符并执行很棒的操作。

movieObservable
    .skip(1)
    .filter(movie -> movie.getRating() == 5)
    .map(movie -> truncate(movie.getSynopsis(), 500));

上面简单的四行代码, 我们跳过了流中发出的第一个测试项,如何过滤出评分5星的电影,然后将每个电影项的概要截断为500个字符,非常的简单好用。

当然,RxJava中还有许许多多其它的运算符,在这里就不一一的去介绍了,可以去官方文档去查询并熟悉。

其它概念

ObserveOn/SubscribeOn

这两个运算符也和前面所说的运算符一样,但他们有一些特殊的用途——控制RxJava中的多线程

subscribeOn()

用于指定Observable在哪个线程执行数据的请求工作。

还是电影的例子,我们需要从网络获取电影的数据,很显然我们需要在后台线程执行,因为Android不允许你在主线程中进行耗时的网络操作。

movieObservable.subscribeOn(Schedulers.io())
    .subscribe(movie -> {
        //处理电影
    }, throwable -> {
        //处理错误
    });

observeOn()

用于指定Observer处理接收到的数据的线程。

假设,你的源Observable发送数据到io线程,但在Android中IO线程是不允许处理界面UI刷新的,因此你需要将数据指定到UI线程中。

movieObservable
    .subscribeOn(Schedulers.io())
    .observeOn(AndroidSchedulers.mainThread())
    .subscribe(movie -> {
        // 处理movie 刷新界面
    }, throwable -> {
        // 处理错误
    })

Schedulers

前面你已经使用了多次Schedulers了,但你可能还在疑惑他到底是什么?

简单来说,Schedulers代表要执行的操作所在的线程。

  • Schedulers.io() —— 操作将会在IO线程中执行,用于网络请求、数据库事务、文件处理等
  • Schedulers.computation() —— 用于计算量很大且需要在一个优化的线程中处理的事务
  • Schedulers.newThread() —— 创建一个新的线程来处理事务。但我们不能无限制的创建新线程,以便可以使用线程池等技术来优化性能
  • AndroidSchedulers.mainThread() —— Android的主线程

OK,学到这里,相信你已经对RxJava有所了解了。接下来还有很长的路要走,比如熟悉各个操作符的使用方式,甚至到研究原理。

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

推荐阅读更多精彩内容

  • 一、Retrofit详解 ·Retrofit的官网地址为 : http://square.github.io/re...
    余生_d630阅读 1,799评论 0 5
  • 响应式编程简介 响应式编程是一种基于异步数据流概念的编程模式。数据流就像一条河:它可以被观测,被过滤,被操作,或者...
    说码解字阅读 3,049评论 0 5
  • 一、RxJava操作符概述 RxJava中的操作符就是为了提供函数式的特性,函数式最大的好处就是使得数据处理简洁易...
    BrotherChen阅读 1,590评论 0 10
  • 一、RxJava操作符概述 RxJava中的操作符就是为了提供函数式的特性,函数式最大的好处就是使得数据处理简洁易...
    无求_95dd阅读 2,968评论 0 21
  • 一、RxJava操作符概述 RxJava中的操作符就是为了提供函数式的特性,函数式最大的好处就是使得数据处理简洁易...
    测天测地测空气阅读 625评论 0 1