加入收藏 | 设为首页 | 会员中心 | 我要投稿 衡阳站长网 (https://www.0734zz.cn/)- 数据集成、设备管理、备份、数据加密、智能搜索!
当前位置: 首页 > 创业 > 经验 > 正文

RxSwift学习教程之类型对象Subject详解

发布时间:2020-12-24 13:36:34 所属栏目:经验 来源:网络整理
导读:前言 在上一篇文章我们介绍了 Observable 的基本概念和使用情形。但是大多数情形下,我们需要在应用运行时添加数据到 Observable 中并将其发送给订阅者。在这种需求场景下,我们就不得不使用 RxSwift 中另一种类型对象了 - Subject 。 在应用中 Subject 实际
副标题[/!--empirenews.page--]

前言

在上一篇文章我们介绍了 Observable 的基本概念和使用情形。但是大多数情形下,我们需要在应用运行时添加数据到 Observable 中并将其发送给订阅者。在这种需求场景下,我们就不得不使用 RxSwift 中另一种类型对象了 - Subject 。

在应用中 Subject 实际上同时扮演了两个不同的角色:既是可观察对象同时也是观察者。这意味着 Subject 实例对象既可以接收事件也可以发送事件。例如,Subject 实例对象可以接收 next 事件信息,然后再将其发送给它自己的订阅者。示例代码:

let subject = PublishSubject<String>()

let subscriptionOne = subject
       .subscribe(onNext: { string in
        print(string)
       })

subject.on(.next("1"))

/* 打印结果:
1
*/

上面代码中使用的是 PublishSubject 类型的示例,而 RxSwift 中总共也四种类型的 Subject:

  • PublishSubject:初始化时并不包含数据,并且只会给订阅者发送后续数据。
  • BehaviorSubject:创建时需要包含初始数据,并且会给订阅者发送后续数据和最近的一次数据。
  • ReplaySubject:创建时需要指定对象缓存区容量,该容量表示会给订阅者重新发送订阅前数据的大小。
  • Variable:BehaviorSubject 对象的封装类型。它会将当前数据保存为状态并且只会给订阅者重新发送最近或者初始值。

下面将详细介绍这四种类型对象的概念以及它们的区别和使用情况。

PublishSubject

如果你仅仅是想让订阅者获取被观察者在生命周期内若产生的数据的话,那么你完全可以选用 PublishSubject 。而且 PublishSubject 对象的行为符合正常的预期,它只会给订阅者发送其订阅开始之后的数据。

例如,下图的最上面的时间线表示被观察者所发送的事件,而下面两个则分别代表不同的观察者。可以看到下面两个观察者都只会接收到订阅后所发送的事件而无法获知之前的情形。

RxSwift学习教程之类型对象Subject详解

对应的代码为:

let subject = PublishSubject<String>()

let subscriptionOne = subject
       .subscribe(onNext: { event in
        print("1) ( event.element ?? event)" )
       })

subject.on(.next("1")) 

let subscriptionTwo = subject
       .subscribe(onNext: { event in
        print("2) (event.element ?? event)")
       })
 
subject.on(.next("2")) 

subject.on(.next("3")) 

/* 打印结果
1) 1
1) 2
2) 2
1) 3
2) 3
*/

如果此时我们取消 subscriptionOne 的订阅并发送新数据的话,那么结果为:

subscriptionOne.dispose()
subject.on(.next("4")) 

 /* 打印结果
 2) 4
 */

另外,当 PublishSubject 对象生命周期结束时,无论后续是否继续有数据产生该对象只会简单的发送之前结束生命周期的事件。

// 结束生命周期
subject.onCompleted()

// 发送新数据
subject.onNext("5")

// 结束观察
subscriptionTwo.dispose()

let disposeBag = DisposeBag()
// 重新进行订阅操作 
subject
 .subscribe { 
  print("3)",$0.element ?? $0) 
 } 
 .addDisposableTo(disposeBag)
// 发送新数据
subject.onNext("?")

/* 打印结果
2) completed
3) completed
 */

对于时序敏感的操作来说,PublishSubject 显然是非常合适的选择。但是并不是所有的情形都时序敏感,有时候我们可能会希望在订阅时能够获知最近一次的数据。此时,我们就需要使用 BehaviorSubject 对象了。

BehaviorSubject

BehaviorSubject 的行为与 PublishSubject 几乎一致,不过前者会给订阅者多发送一个最近的数据。图解如下:

RxSwift学习教程之类型对象Subject详解

图示中最上面对应的是所发射的数据,其中第二行表示第一个观察者,第三行则表示另一个。可以发现第一个观察者是在 1 之后 2 之前进行观察的,但是它依然能够获取到数据 1 。我们可以通过代码进行验证:

let subject = BehaviorSubject(value: "1")
let bag = DisposeBag()

subject
 .subscribe { event in
   print("1) event: (event.element!) ")
 }
 .addDisposableTo(bag)

subject
 .subscribe { event in
  print("2) event: (event.element!) ")
 }
 .addDisposableTo(bag)

subject.onNext("2")

subject
 .subscribe { event in
  print("3) event: (event.element!) ")
 }
 .addDisposableTo(bag)

subject.onNext("3")

因为始终都能获取到最近的数据,所以对于那些可能需要默认值的场景,BehaviorSubject 显然是一个好的选择。

ReplaySubject

ReplaySubject 与 BehaviorSubject 的行为非常接近,只不过前者允许订阅者获取多于 1 个的最近数据。所以从某种意义上来说,后者是前者的一个特例。

下图就是一个 buffer 大小为 2 的 ReplaySubject 对象。它总过发射了三次数据,其中第一个观察者获取了所以的数据。而第二个观察者虽然是在第二个数据发射后才开始,但它依旧能获取缓存区中保存的数据。

RxSwift学习教程之类型对象Subject详解

代码表示如下:

let subject = ReplaySubject<String>.create(bufferSize: 2)

let bag = DisposeBag()

subject
 .subscribe { event in
  print("1) event: (event.element!) ")
 }
 .addDisposableTo(bag)

subject.onNext("1")

subject.onNext("2")

subject
 .subscribe { event in
  print("2) event: (event.element!) ")
 }
 .addDisposableTo(bag)

subject.onNext("3")

/* 打印结果:
1) event: 1 
1) event: 2 
2) event: 1 
2) event: 2 
1) event: 3 
2) event: 3 
*/

(编辑:衡阳站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

热点阅读