RxSwift - Observable 阅读笔记

什么是 Observable

在 RxSwift 中,所有的事件都是基于队列 (sequence) 的,Observable 会不断在这条队列上发送数据 / 数据序列。而我们通过订阅 Observable ,当有事件被发送,就可以接受到事件通知。

Observable

Observable 生命周期

Observable 会发送三种事件类型,发送包含事件 element 的 next 事件,发送 completed 事件,作为事件序列的完结。

Completed

当有错误发生时,Observable 会发送包含错误信息的 error(Error) 事件。

Error

Observable 可以一直发送 next 事件,直到发送了 error 或者 completed 事件,这条事件序列才会被终止。

Observable 的创建

RxSwift 提供了一系列创建 Observable 的方法

  • just

    创建一个只包含一个事件的序列。

    Observable<Int>.just(1)
    
  • of

    创建一个事件序列,包含参数中传递的事件

    Observable.of(1, 2, 3)
    
  • from

    通过 sequence 创建事件序列。

    Observable.from([1, 2, 3])
    
  • never

    创建一个不会传递任何事件也不会终止的序列

     Observable<Void>.never()
    
  • empty

    创建一个只发送 completed 事件的序列

    Observable<String>.empty()
    
  • error

    创建一个只发送 error 事件的序列

    Observable<String>.error(MyError.error)
    
  • range

    创建一个在某个范围内的 int 值的序列

    Observable<Int>.range(start: 1, count: 10)
    

订阅 Observable

RxSwift 使用 subscribe() 来订阅 Observable。这里需要强调的是,任何 Observable 只有在有订阅者时才会发送事件,因此,例如上文提及的 Observable.of(1, 2, 3) 其实没有发送任何事件。只有当通过 subscribe() 订阅时,Observable 才会发送事件

Observable<Int>
    .of(1, 2, 3)
    .subscribe({ event in
        print(event)
    })

打开控制台,就会得到下面的打印结果

next(1)
next(2)
next(3)
completed

定义的 Observable 对象为每个元素发送了 .next 事件。最后发送了 .completed 事件,作为事件序列的结束。

.next 事件的元素是一个 Optional ,因此当需要直接访问这个值时,需要做解包操作

不过 RxSwift 提供了另一种订阅函数来满足订阅要求。

Observable<Int>
    .of(1, 2, 3)
    .subscribe(onNext: { (element) in
        print(element)
    }, onError: { (error) in
        print(error)
    }, onCompleted: {
        print("Completed")
    }, onDisposed: {
        print("Disposed")
    })

Observable 处理与终止

Observable 有订阅者时,才会开始不断发送 .next 事件,直到发送一个 .error 或者 .completed 事件,事件序列结束

我们可以手动的通过取消订阅来终止这个事件序列。

  • 单独的为每一个 Observable 添加取消订阅操作

    Observable
        .of(1, 2, 3)
        .subscribe(onNext: { (element) in
            print(element)
        }, onCompleted: {
            print("completed")
        }, onDisposed: {
            print("Disposed")
        })
        .dispose()
    

    控制台的打印结果变成了

    1
    2
    3
    completed
    Disposed
    

    在调用了 dispose() 方法之后,当前的 Observable 对象就停止向订阅者发送消息了。

  • 统一管理 Observable 的释放

    为每一个 Observable 都添加 dispose() 方法不仅显得多余,并且如果在多个地方使用到这个 Observable 对象,在某处提前释放了,可能会导致一些意想不到的问题。RxSwift 提供了一个 DisposeBag 来统一管理 Observable 的释放问题

    let bag = DisposeBag()
    Observable
        .of(1, 2, 3)
        .subscribe(onNext: { (element) in
            print(element)
        })
        .addDisposableTo(bag)
    

    首先定义一个 DisposeBag 对象,之后就像使用 dispose() 一样,在订阅之后使用 addDisposableTo(_ bag: RxSwift.DisposeBag)Observable 添加到定义的 DisposeBag 对象中。

    DisposeBag 将是后面经常使用到的处理 Observable 回收的方法。

自定义事件

循规蹈矩的 Observable 的创建方式,或多或少都无法满足日常 PM 的需求。所以如何创建包含自定义事件的数据流呢?RxSwift 提供了两种方式

  • create

    let disposeBag = DisposeBag()
    enum MyError: Error {
        case anError
    }
    Observable<String>
        .create({ (observer) in
            observer.onNext("1")
            observer.onError(MyError.anError)
            observer.onCompleted()
            observer.onNext("where is it?")
            return Disposables.create()
        })
    

    create 函数定义

    public static func create(_ subscribe: @escaping (RxSwift.AnyObserver<RxSwift.Observable.E>) -> Disposable) -> RxSwift.Observable<RxSwift.Observable.E>

    在传递的闭包内部,我们可以自定义事件,对上述的 Observable 订阅,我们将接收到下列事件

    1
    anError
    Disposed
    

    在接收到 .error 事件之后,整个事件序列就被终止了。

  • deferred 创建一个生成不同的事件序列的工厂方法

    试想这样的使用场景,对于同一个 Observable,我们希望不同的订阅者能订阅到不同的数据流。

    let disposeBag = DisposeBag()
    var flip = false
    let factory: Observable<Int> = Observable.deferred({
        flip = !flip
        
        if flip {
            return Observable.of(1, 2, 3)
        } else {
            return Observable.of(4, 5, 6)
        }
    })
    for _ in 0 ... 3 {
        factory.subscribe(onNext: {
            print($0, terminator: "")
        })
        .disposed(by: disposeBag)
        print()
    }
    

    每个订阅 factory 的订阅者,都能获得不同的事件序列,控制台的打印结果为

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

推荐阅读更多精彩内容

  • 发现 关注 消息 RxSwift入坑解读-你所需要知道的各种概念 沸沸腾关注 2016.11.27 19:11*字...
    枫叶1234阅读 2,780评论 0 2
  • 最近在学习RxSwift相关的内容,在这里记录一些基本的知识点,以便今后查阅。 Observable 在RxSwi...
    L_Zephyr阅读 1,740评论 1 4
  • 本文章内部分图片资源来自RayWenderlich.com 本文结合自己的理解来总结介绍一下RxSwift最基本的...
    FKSky阅读 2,856评论 4 14
  • 如果你要补钙,还是应该通过吃其他富含钙质的食物,比如说牛奶来补。而不要想通过喝骨头汤来补。因为:1、骨头里含有很多...
    做个懂科学的憨人阅读 310评论 0 2
  • 萌猫“胖花”的主人Yixi有事回国一个月,走之前把宠猫托付给了我。我和Alex (以下称轻松熊)早就满怀期待,代管...
    Shou撕鬼子阅读 486评论 0 3