BehaviorSubject和PublishSubject的区别

53

我正在尝试理解以下问题的黄金法则(如果有):

何时使用 BehaviorSubject?

何时使用 PublishSubject?

它们之间的区别非常明显。

有许多种类型的 subjects。对于这个具体的要求,PublishSubject 很适合,因为我们希望从上次离开的地方继续这个序列。所以假设事件 1、2、3 在 (B) 中被发送,那么在 (A) 再次连接后,我们只想看到 4、5、6。如果我们使用 ReplaySubject,我们会看到 [1, 2, 3],4,5,6;或者如果我们使用 BehaviorSubject,则会看到 3,4,5,6 等。(来源:如何思考 RxJava 中的 Subjects(第一部分)

我发现 Subject 在两个上下文中被使用(至少),UI 上下文和监听器上下文。

  • UI 上下文(MVVM 作为例子)

例如,在这里使用了一个 BehaviorSubject ,很明显为什么使用了 Subject 而不是 Observable,但我把 BehaviorSubject 改成了 PublishSubject,但应用程序的行为仍然相同。

  • 监听器上下文

为什么他们将project 字段设为 BehaviorSubject 而不是 PublishSubject


一个小示例,展示它们之间的区别:https://github.com/selmanon/BehaviorAndPublishSubjectDemo - TooCool
4个回答

44

PublishSubjectBehaviorSubject的主要区别在于后者会记住最后一个已发出的项。正因为如此,当你想要发出状态时,BehaviorSubject非常有用。

可能是因为他们想通过这种方法检索到最后一个已发出的项目,所以将项目字段设置为BehaviorSubject而不是PublishSubject

@Override public @NonNull Observable<Project> project() {
  return this.project;
}

1
它只会发出状态更改,还是即使状态更改为相同的先前值也会发出?例如,如果我放置onNext('Adam'),onNext('Adam'),onNext('Smith'),它会仅发出Adam后跟Smith吗? - Saifur Rahman Mohsin
1
@SaifurRahmanMohsin 请参阅https://github.com/akarnokd/RxJava2_9/blob/master/src/main/java/io/reactivex/subjects/BehaviorSubject.java#L267。它没有检查当前值是否已更改。 - Navneeth

40

PublishSubject:开始为空,并仅向订阅者发布新元素。因为PublishSubject在创建后立即开始发出元素,所以在Subject创建和观察者订阅之间,可能会丢失一个或多个项目。

BehaviorSubject:它需要一个初始值并将其重复播放或最新元素提供给新的订阅者。由于BehaviorSubject总是发布最新元素,因此您无法创建没有给定默认初始值的BehaviorSubjectBehaviorSubject 对于描述“随时间变化的值”很有帮助。例如,生日事件流是一个Subject,但一个人年龄的流则是BehaviorSubject


21

发布主题(Publish Subject):如果一个学生迟到进入教室,他只想从他进入教室的那个时间点开始听课。因此,发布主题是这种情况下最好的选择。

行为主题(Behavior Subject):如果一个学生迟到进入教室,他希望听到教授正在讲授的最新事情(而不是从一开始),以便了解上下文的概念。所以,在这里我们将使用行为主题。


2
喜欢这个易于理解的替代经典技术解释的描述。谢谢! - kjanderson2
发布主题(Publish Subject):“从他进入的那个时间点开始收听。” 行为主题(Behavior Subject):“收听最近的事物。”感谢您的描述,但我仍然觉得有点困惑。两者对我来说意思是一样的。请您再解释一下。 - Anmol Singh
1
@AnmolSingh,假设我们进入数学课堂,老师教授加法、减法、乘法和除法。老师已经讲解了加法和减法,乘法和除法留到以后再讲。如果你现在进入课堂,并且是“行为主体”,那么你将学习乘法和除法。如果你是“结果主体”,那么在你进入课堂之前,老师已经讲解了减法,因此你将学习减法、乘法和除法。 - Shubham Jain

2
BehaviourSubject和PublishSubject的区别在于它们保留捕获数据的时间长度。例如,PublishSubject仅保留当前可用的数据并在每次输入时更新,而BehaviourSubject保留最后插入的数据。因此,您可以将其用于例如在注册表单中确认密码,并且作为PublishSubject的示例,在执行搜索时,必须不断更新数据以提供准确的结果,并且没有太多必要比较正在插入的数据。
作为参考,我从http://reactivex.io/documentation/subject.html中提供了这两张照片。 PublishSubject BehaviourSubject

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接