shareReplay(bufferSize:Int)
使观察者共享Observable
,观察者会立即收到最新的元素,即使这些元素是在订阅前产生的。bufferSize表示缓存最新的n个元素,将这些元素直接发送给新的观察者。
func shareReplay() {
print("\n shareReplay test---")
let disposeBag = DisposeBag()
let testReplay = Observable.just("laught cry").map { print($0) } // 没使用shareReplay
//let testReplay = Observable.just("laught cry").map { print($0) }.shareReplay(1)// 使用shareReplay
// 1.创建第一个序列
testReplay
.subscribe { event in
print(event)
}.addDisposableTo(disposeBag)
// 2.创建第二个序列
testReplay
.subscribe { event in
print(event)
}.addDisposableTo(disposeBag)
}
// 没使用shareReplay共享Observable 两次订阅同一Observable,执行两次laught cry
shareReplay test---
laught cry
next(())
completed
laught cry
next(())
completed
// 使用shareReplay共享了Observable 两次订阅同一Observable,只执行一次laught cry
shareReplay test---
laught cry
next(())
completed
next(())
completed
那么问题来了,shareReplay(bufferSize:Int)中bufferSize的作用是什么?为什么是1?换成其他数值会如何呢?
当有多个订阅者去订阅同一个 Observable 的时候,我们不希望 Observable 每次有新的订阅者都去执行。RxSwift 提供了很多操作:
share() 、 replay() 、 replayAll() 、 shareReplay() 、 publish() 、 shareReplayLatesWhileConnected() , 这么多个,应该选哪一个?我们先总体的了解一下:
1 表示重播最多 bufferSize 个事件 ;2 表示当订阅者的引用计数大于0时,重播一个事件。
*共享订阅者 Shared subscription*
多个订阅者订共享一个订阅者对象
*可连接 Connectable*
可连接序列只有调用 connect 后才会开始发射值,可以等多个订阅者订阅后再连接。
*引用计数 Reference counting*
返回的 observable 记录了订阅者的数量,当订阅者数量从0变成1,订阅源序列,当订阅者数量从1变成0,取消订阅并重置源序列。
每次订阅者数量从0变成1源序列将会重新被订阅。
*重播事件*
重播已经发射的事件给订阅者。
replay(bufferSize) 和 shareReplay(bufferSize) 最多重播 bufferSize 个,
shareReplayLatestWhileConnected 最多一个,
当订阅者的引用计数变成0, buffer 会被清空,所以引用计数从0变成1,订阅者不会受到重播事件。
举个栗子
let disposeBag = DisposeBag()
var results:Observable<String>!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
// 模拟用户不断输出的文本
results = Observable<Int>
.interval(2, scheduler: MainScheduler.instance)
.map{
"\($0)"
}
.flatMapLatest{ query in
self.request(query)
}
shareReplay()
}
// 延迟执行
func delay(_ delay: Double, closure: @escaping () -> Void) {
DispatchQueue.main.asyncAfter(deadline: .now() + delay) {
closure()
}
}
// 模拟网络请求操作
func request(_ query:String) -> Observable<String>{
return Observable.create{
observer in
print("搜索 \(query) 发送网络请求")
observer.onNext("\(query) 请求成功!")
return Disposables.create {
}
}
}
func shareReplay(){
let results = self.results.shareReplay(1)
let sub1 = results.subscribe{
print("订阅者 one: \($0)")
}
let sub2 = results.subscribe{
print("订阅者 two: \($0)")
}
delay(5){
print("订阅者sub1 销毁")
sub1.dispose()
print("订阅者sub2 销毁")
sub2.dispose()
print("three 订阅")
results.subscribe{
print("订阅者 three: \($0)")
}.disposed(by: self.disposeBag)
}
}
销毁 + ( bufferSize = 1)
搜索 0 发送网络请求
订阅者 one: next(0 请求成功!) // 记录了订阅者的数量 1
订阅者 two: next(0 请求成功!) // 记录了订阅者的数量 2
搜索 1 发送网络请求
订阅者 one: next(1 请求成功!)
订阅者 two: next(1 请求成功!)
订阅者sub1 销毁 // 记录了订阅者的数量 1
订阅者sub2 销毁 // 记录了订阅者的数量 0 -->buffer清空重置订阅序列
three 订阅 // 订阅者的数量 1
// three接收最后的一次缓存结果
订阅者 three: next(1 请求成功!)
// 重新开始
搜索 0 发送网络请求
订阅者 three: next(0 请求成功!)
搜索 1 发送网络请求
订阅者 three: next(1 请求成功!)
搜索 2 发送网络请求
订阅者 three: next(2 请求成功!)
搜索 3 发送网络请求
订阅者 three: next(3 请求成功!)
....
销毁 + ( bufferSize = 2)
搜索 0 发送网络请求
订阅者 one: next(0 请求成功!) // 记录了订阅者的数量 1
订阅者 two: next(0 请求成功!) // 记录了订阅者的数量 2
搜索 1 发送网络请求
订阅者 one: next(1 请求成功!)
订阅者 two: next(1 请求成功!)
订阅者sub1 销毁 // 记录了订阅者的数量 1
订阅者sub2 销毁 // 记录了订阅者的数量 0 --> buffer清空重置订阅序列
three 订阅 // 订阅者的数量 1
// three接收最后的两次缓存结果
订阅者 three: next(0 请求成功!)
订阅者 three: next(1 请求成功!)
// 重新开始
搜索 0 发送网络请求
订阅者 three: next(0 请求成功!)
搜索 1 发送网络请求
订阅者 three: next(1 请求成功!)
搜索 2 发送网络请求
订阅者 three: next(2 请求成功!)
搜索 3 发送网络请求
订阅者 three: next(3 请求成功!)
....
不销毁 + ( bufferSize = 1)
搜索 0 发送网络请求
订阅者 one: next(0 请求成功!)
订阅者 two: next(0 请求成功!)
搜索 1 发送网络请求
订阅者 one: next(1 请求成功!)
订阅者 two: next(1 请求成功!)
three 订阅 // 记录订阅者数量 3
//three 接收最后的一次缓存结果
订阅者 three: next(1 请求成功!)
// buffer未清空 不会重置订阅序列
搜索 2 发送网络请求
订阅者 one: next(2 请求成功!)
订阅者 two: next(2 请求成功!)
订阅者 three: next(2 请求成功!)
搜索 3 发送网络请求
订阅者 one: next(3 请求成功!)
订阅者 two: next(3 请求成功!)
订阅者 three: next(3 请求成功!)
搜索 4 发送网络请求
订阅者 one: next(4 请求成功!)
订阅者 two: next(4 请求成功!)
订阅者 three: next(4 请求成功!)
....
不销毁 + ( bufferSize = 2)
搜索 0 发送网络请求
订阅者 one: next(0 请求成功!)
订阅者 two: next(0 请求成功!)
搜索 1 发送网络请求
订阅者 one: next(1 请求成功!)
订阅者 two: next(1 请求成功!)
three 订阅 // 记录订阅者数量 3
//three 接收最后的两次缓存结果
订阅者 three: next(0 请求成功!)
订阅者 three: next(1 请求成功!)
// buffer未清空 不会重置订阅序列
搜索 2 发送网络请求
订阅者 one: next(2 请求成功!)
订阅者 two: next(2 请求成功!)
订阅者 three: next(2 请求成功!)
搜索 3 发送网络请求
订阅者 one: next(3 请求成功!)
订阅者 two: next(3 请求成功!)
订阅者 three: next(3 请求成功!)
搜索 4 发送网络请求
订阅者 one: next(4 请求成功!)
订阅者 two: next(4 请求成功!)
订阅者 three: next(4 请求成功!)
....
参考文档:https://medium.com/@_achou/rxswift-share-vs-replay-vs-sharereplay-bea99ac42168