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

results matching ""

    No results matching ""