RxSwift_操作符_share(replay:scope:)
share(replay:scope:) 作用:
解决有多个订阅者
的情况下,避免
事件转换操作符(比如:map、flatMap、flatMapLatest等等
)被多次执行的问题
#普通的可观察序列
let seq = PublishSubject()
let ob = seq.map { (i) -> Int in
print("map 被调用 :---\(i)")
return i * 2
}let _ = ob.subscribe(onNext: { (num) in
print("--第一次订阅--\(num)")
}, onError: nil, onCompleted: nil, onDisposed: nil)let _ = ob.subscribe(onNext: { (num) in
print("--第二次订阅--\(num)")
}, onError: nil, onCompleted: nil, onDisposed: nil)seq.onNext(1)/// 打印结果:
/// map 被调用 :---1
/// --第一次订阅--2
/// map 被调用 :---1
/// --第二次订阅--2
#带share let seq = PublishSubject()
let ob = seq.map { (i) -> Int in
print("map 被调用 :---\(i)")
return i * 2
}
/// replay:缓存的事件个数
/// scope:subject是否独立(使用说明请看下方)
.share(replay: 0, scope: .forever)let _ = ob.subscribe(onNext: { (num) in
print("--第一次订阅--\(num)")
}, onError: nil, onCompleted: nil, onDisposed: nil)let _ = ob.subscribe(onNext: { (num) in
print("--第二次订阅--\(num)")
}, onError: nil, onCompleted: nil, onDisposed: nil)seq.onNext(1)/// 打印结果:
/// map 被调用 :---1
/// --第一次订阅--2
/// --第二次订阅--2
看了上面的两个例子,貌似已经懂得share操作符的基本使用,嘻嘻嘻嘻总结
:
从上面例子可以知道:
发送一次onNext事件,就对应一个Observable,而所有的观察者都只对应这个Observable,Observable共享给所有的观察者
share(replay:scope:)
操作符使得观察者共享Observable
,并且缓存最新的n个元素
,将这些元素直接发送给新的观察者
请继续看下面的例子
# 代码一:没有使用sharelet net = Observable.create { (ob) -> Disposable in
print("我开始网络请求了")
ob.onNext("请求结果")
ob.onCompleted()
return Disposables.create {
print("销毁了")
}
}net.subscribe(onNext:{
print("第一次订阅:\($0)",Thread.current)
}).disposed(by: bag)net.subscribe(onNext:{
print("第二次订阅:\($0)",Thread.current)
}).disposed(by: bag)/// 打印结果:
/// 我开始网络请求了
/// 第一次订阅:请求结果 {number = 1, name = main}
/// 销毁了
/// 我开始网络请求了
/// 第二次订阅:请求结果 {number = 1, name = main}
/// 销毁了
# 代码二:share(replay: 0, scope: .whileConnected)let net = Observable.create { (ob) -> Disposable in
print("我开始网络请求了")
ob.onNext("请求结果")
ob.onCompleted()
return Disposables.create {
print("销毁了")
}
}.share(replay: 0, scope: .whileConnected)net.subscribe(onNext:{
print("第一次订阅:\($0)",Thread.current)
}).disposed(by: bag)net.subscribe(onNext:{
print("第二次订阅:\($0)",Thread.current)
}).disposed(by: bag)/// 打印结果:
/// 我开始网络请求了
/// 第一次订阅:请求结果 {number = 1, name = main}
/// 销毁了
/// 我开始网络请求了
/// 第二次订阅:请求结果 {number = 1, name = main}
/// 销毁了
首先通过上面两端代码的打印结果,发现share貌似也不起什么作用,其实不然。讲这个之前,请先看RxSwift中对share方法中对
scope参数的注释
* `.whileConnected`
// Each connection will have it's own subject instance to store replay events.
// Connections will be isolated from each another.
// source.multicast(makeSubject: { Replay.create(bufferSize: replay) }).refCount()* `.forever`
// One subject will store replay events for all connections to source.
// Connections won't be isolated from each another.
// source.multicast(Replay.create(bufferSize: replay)).refCount()
scope
是一个枚举值,包括whileConnected、forever
官方文档注释的大概意思是:
whileConnected:每个connection 都有单独的一个Subject存储事件Event
forever:用一个Subject存储所有的connections的事件Event
为了理解这个,我们将“代码二”中的.whileConnected 修改为 .forever
看看结果有什么不一样的
#代码三let net = Observable.create { (ob) -> Disposable in
print("我开始网络请求了")
ob.onNext("请求结果")
ob.onCompleted()
return Disposables.create {
print("销毁了")
}
}.share(replay: 0, scope: .forever)net.subscribe(onNext:{
print("第一次订阅:\($0)",Thread.current)
})
.disposed(by: bag)net.subscribe(onNext:{
print("第二次订阅:\($0)",Thread.current)
}).disposed(by: bag)/// 打印结果:
/// 我开始网络请求了
/// 第一次订阅:请求结果 {number = 1, name = main}
/// 销毁了
发现打印结果,少了订阅2。这是为什么了?
根据注释,.forever 是使用一个Subject存储所有的连接的Event,
在第一次订阅的时候,触发Observable的构建函数,但是在发送事件完之后就发送了complete,既然已经发送了complete那么代表存储的Subject已经结束了,所以第二次订阅并没有打印
PS: 这种情况如果想要实现多次订阅,然后只执行一次网络请求的,可以参考这个文章的解决方案:使用功能操作符项目使用 【RxSwift_操作符_share(replay:scope:)】项目比较常用的可能就是. publish
封装网络请求的Observable
中,在Observable中添加share(replay:scope:)操作符,目的是为了在多个位置订阅,避免发一次的Event,而重复多个请求
推荐阅读
- JavaScript|JavaScript 的new操作做了什么()
- 一文教你如何用Python轻轻松松操作Excel|一文教你如何用Python轻轻松松操作Excel,Word,CSV
- linux操作系统-僵尸进程与孤儿进程
- Shell-Bash变量与运算符
- 2.6|2.6 Photoshop操作步骤的撤消和重做 [Ps教程]
- MongoDB,Wondows下免安装版|MongoDB,Wondows下免安装版 (简化版操作)
- 一起来学习C语言的字符串转换函数
- C语言字符函数中的isalnum()和iscntrl()你都知道吗
- 在线版的迅捷思维导图怎么操作()
- 操作系统|[译]从内部了解现代浏览器(1)