- 首先我们创建一个:
序列的中的序列 - string - 映射 - 序列
,并且发起多次订阅
,如下代码:
//创建序列
let result = inputTF.rx.text.skip(1)
.flatMap { [weak self](input) -> Observable in
return (self?.dealwithData(inputText:input ?? ""))!
}
//连续订阅两次
result.subscribe(onNext: { (element) in
print("订阅到了--:\(element)")
})
result.subscribe(onNext: { (element) in
print("订阅到了--:\(element)---\(Thread.current)")
})
//模拟网络请求
func dealwithData(inputText:String)-> Observable{
print("请求网络了 \(Thread.current)") // data
return Observable.create({ (ob) -> Disposable in
if inputText == "1234" {
ob.onError(NSError.init(domain: "com.smart_M.cn", code: 10086, userInfo: nil))
}// json - model username pasword
// username passopp - lgError - 8001 - httpCoder 100 - 500
// 封装 vm - error -
DispatchQueue.global().async {
print("发送之前看看: \(Thread.current)")
ob.onNext("已经输入:\(inputText)")
ob.onCompleted()
}
return Disposables.create()
})
运行代码,并在inputTF
输入内容1
,打印如下:
请求网络了 {number = 1, name = main}
发送之前看看: {number = 4, name = (null)}
请求网络了 {number = 1, name = main}
订阅到了--:已经输入:1
发送之前看看: {number = 5, name = (null)}
订阅到了--:已经输入:1---{number = 5, name = (null)}
输入内容1234
, 打印error
如下:
请求网络了 {number = 1, name = main}
Unhandled error happened: Error Domain=com.lgcooci.cn Code=10086 "(null)"
subscription called from:
发送之前看看: {number = 7, name = (null)}
请求网络了 {number = 1, name = main}
Unhandled error happened: Error Domain=com.lgcooci.cn Code=10086 "(null)"
subscription called from:
发送之前看看: {number = 6, name = (null)}
从上面的打印可以看出:
- 多次订阅就会多次请求,
浪费网络
- 数据请求回来以后还在是
子线程
- 多次执行错误事件
解决方法:
- 开启网络共享
.share(replay: 1, scope: .whileConnected)
- 切换到主线程跟新UI
.observeOn(MainScheduler())
3.检测错误事件(不会反悔error,导致崩溃)
.catchErrorJustReturn("检测到了错误事件")
- 完整代码:
let result = inputTF.rx.text.skip(1)
.flatMap { [weak self](input) -> Observable in
return (self?.dealwithData(inputText:input ?? ""))!
.observeOn(MainScheduler())
.catchErrorJustReturn("检测到了错误事件")
}
.share(replay: 1, scope: .whileConnected)
- 执行结果如下:
----------输入1:
请求网络了 {number = 1, name = main}
发送之前看看: {number = 5, name = (null)}
订阅到了--:已经输入:1
订阅到了--:已经输入:1---{number = 1, name = main}
----------输入1234:
请求网络了 {number = 1, name = main}
订阅到了--:检测到了错误事件
订阅到了--:检测到了错误事件---{number = 1, name = main}
发送之前看看: {number = 6, name = (null)}
上面的问题虽然解决了,但是:
- 我们修改了很多代码,那有没有更好的解决方案呢
- 这时候就该我们的老司机
Driver
出场了
Driver 的简单使用
- 网络共享
- 绑定到了UI - 主线程
- 直接处理错误,返回 非error(直接显示在UI)
//observale -> driver
let result = inputTF.rx.text.orEmpty
.asDriver()
.flatMap {
return self.dealwithData(inputText: $0)
.asDriver(onErrorJustReturn: "检测到了错误事件")
}
// 绑定到了UI - 主线程
// titlt - 非error
result.map { "长度: \(($0 as! String).count)"}.drive(self.textLabel.rx.text)
result.map { "\($0 as! String)"}
.drive(self.btn.rx.title())
执行代码打印如下:
Driver 源码解析
asDriver
是ControlProperty
的扩展方法,返回一个Driver
对象
extension ControlProperty {
public func asDriver() -> Driver {
return self.asDriver { _ -> Driver in
#if DEBUG
rxFatalError("Somehow driver received error from a source that shouldn't fail.")
#else
return Driver.empty()
#endif
}
}
}
Driver
又是SharedSequence
的序列别名
public typealias Driver = SharedSequence
- 网络共享:
source.share(replay: 1, scope: .whileConnected)
public struct DriverSharingStrategy: SharingStrategyProtocol {
public static var scheduler: SchedulerType { return SharingScheduler.make() }
public static func share(_ source: Observable) -> Observable {
return source.share(replay: 1, scope: .whileConnected)
}
}
- 切换到主线程: 进入上边
SharingScheduler
内部make()
方法
public enum SharingScheduler {
/// Default scheduler used in SharedSequence based traits.
public private(set) static var make: () -> SchedulerType = { MainScheduler() }
}
- 错误处理:
ObservableConvertibleType
的扩展方法public func asDriver(onErrorJustReturn: Element) -> Driver
中:
observeOn(DriverSharingStrategy.scheduler
进行线程调度catchErrorJustReturn(onErrorJustReturn)
错误处理
extension ObservableConvertibleType {
...
public func asDriver(onErrorJustReturn: Element) -> Driver {
let source = self
.asObservable()
.observeOn(DriverSharingStrategy.scheduler)
.catchErrorJustReturn(onErrorJustReturn)
return Driver(source)
}
...
}