RxSwift .Share()
当你使用 RxSwift 和 Rx 时,你会不时地发现一些新的信息,这些信息对你来说并不是那么明显,直到你碰到了一堵墙,不得不深入挖掘。其中一个常见的陷阱就是资源共享的概念。在 RxSwift 中,这通常由 share ()操作符表示。
在深入研究 share ()如何以及何时有用,甚至是必需的细节之前,让我们尝试用一个非常常见的例子来说明手头的问题:

你有一个结果流,它对用户在按钮上的点击做出反应,并向某个 API 服务发出网络请求。您将这个结果映射到朋友的姓名和电话号码的两个单独的流中。
稍后,在你的视图控制器中,你可以订阅这个名字和电话信息流,当你的用户点击一个按钮时,你就可以得到最新朋友的名字和电话:


这可能看起来像是一段无害的代码,但是它并不像一开始看起来那么简单。
在下面的例子中ーー每次你订阅电话或名称ーー你实际上会得到一个完全不同的流,这意味着每次订阅都会得到一个完全不同的网络请求!

如果你开始分支并进一步描绘你的产出,情况会变得更糟:

每个映射基本上是另一个订阅,从而创建额外的独立资源和流ーー导致触发额外的网络请求。

在这种情况下ー每次点击按钮就会触发4个网络请求。
幸运的是,存在一个非常有用的操作符 share ()来解决这个特定的问题
它允许您定义在订阅者之间共享资源的流。这意味着,流的每个订阅者将获得完全相同的流,并且不会为原始流调用额外的计算或资源。
在上面的例子中,如果你只是将原来的 flatMapLatest 例子更改为下面的例子,那么你的整个问题都会得到解决,每次点击只会触发一个网络请求

在你的信息流中添加了 share ()后,下面是上面的图表:

这里有另一个简单的例子来证明这一点。下面的代码有一个方法,getUniqueId () ,它返回一个可观察的 < string > ,当它被订阅的时候返回一个唯一标识符。
第一个示例没有 share ()操作符。请注意,即使所有3个订阅者声称订阅了同一个 ID ーー他们获得的是不同的流,你实际上会看到每个订阅者有不同的 ID

只需在 ID 流的末尾添加 share ()操作符,就可以使这种情况更加可预期,并且您将在该流的所有订阅者中看到相同的 ID

当调用 share ()时,实际上是调用 share (replay: 0,scope:)。因为这些是此运算符的默认参数值,所以在不知不觉中调用了。
基本意思是“你希望我向新订阅者重播多少个元素? ”
默认值0使您的流的行为更像 PublishSubject ー例如,订阅者只能获得流发出的未来值,但不知道在订阅点之前发生的任何事情。
相比之下,设置大于0的重播值类似于 BehaviorSubject (对于1的重播)或 ReplaySubject (对于大于1的重播)ーー例如,每个新订阅者将重播订阅点之前的最后 x 事件,以及未来的任何排放

发表回复