Driver的使用
Driver的特性
1. 不会产生error
事件
2. 一定在MainScheduler
监听(主线程监听)
3. 共享附加作用
Driver是一个精心准备的特征序列,它主要是为了简化UI层的代码,更安全的进行UI元素的绑定。
那么Dirver
到底是做什么的?与其他的Observable
有什么区别?接下来通过示例来分析一下;场景描述:用户输入内容,内容作为参数,在子线程发起一个请求,回到主线程订阅两次,监听响应结果;
func testObservable() { let observable = textField.rx.text.skip(1).flatMap {[weak self] (text) -> Observable<String> in guard let `self` = self else { return Observable.just("") }//释放之后,如果还来到这self为空的时候发出一个空字符串信号 // subscribe(on: ConcurrentDispatchQueueScheduler.init(qos: .userInitiated)) 在后台构建序列 return self.dealwithData(inputText: text ?? "").subscribe(on: ConcurrentDispatchQueueScheduler(qos: .userInitiated)) } observable.subscribe { (result) in Logger("第一次订阅 \(result) - 线程 - \(Thread.current)") }.disposed(by: disposeBag) observable.subscribe { (result) in Logger("第二次订阅 \(result) - 线程 - \(Thread.current)") }.disposed(by: disposeBag) }
运行结果:
Log - 开始模拟发起请求 当前线程 - <NSThread: 0x6000027cf340>{number = 9, name = (null)} Log - 第一次订阅 next(已经输入: 21) - 线程 - <NSThread: 0x6000027cf340>{number = 9, name = (null)} Log - 开始模拟发起请求 当前线程 - <NSThread: 0x6000027cf340>{number = 9, name = (null)} Log - 第二次订阅 next(已经输入: 21) - 线程 - <NSThread: 0x6000027cf340>{number = 9, name = (null)}
通过log
可以发现正常情况下订阅了两次、子线程请求了两次网络,订阅的结果依然是在子线程,请求了两次意味着非共享附加作用
;
如果我想实现订阅两次,子线程仅请求一次网络,并把订阅的结果回到主线程该怎么做呢?我们可以这样做,通过observe(on: MainScheduler.instance)
回到主线程
,利用share(replay: 1, scope: .whileConnected)
保证多次订阅只发起一次请求,此为共享附加作用
;如代码所示:
func testMainObservable() { let observable = textField.rx.text.skip(1).flatMap {[weak self] (text) -> Observable<String> in guard let `self` = self else { return Observable.just("") } // subscribe(on: ConcurrentDispatchQueueScheduler.init(qos: .userInitiated)) 在后台构建序列 return self.dealwithData(inputText: text ?? "").subscribe(on: ConcurrentDispatchQueueScheduler(qos: .userInitiated)) }.observe(on: MainScheduler.instance).share(replay: 1, scope: .whileConnected) observable.subscribe { (result) in Logger("第一次订阅 \(result) - 线程 - \(Thread.current)") } onError: { (error) in Logger(error)//.catchAndReturn("error") }.disposed(by: disposeBag) observable.subscribe { (result) in Logger("第二次订阅 \(result) - 线程 - \(Thread.current)") } onError: { (error) in Logger(error) }.disposed(by: disposeBag) }
运行结果:
Log - 开始模拟发起请求 当前线程 - <NSThread: 0x600003d4db00>{number = 7, name = (null)} Log - 第一次订阅 已经输入: 21 - 线程 - <NSThread: 0x600003d08900>{number = 1, name = main} Log - 第二次订阅 已经输入: 21 - 线程 - <NSThread: 0x600003d08900>{number = 1, name = main}
通过运行结果可以看到,上述方式已经满足了我们的需求,那么有没有更简单的方式。来实现上述需求呢?
这个时候利用driver
,调用asDriver(onErrorJustReturn: "drive error")
,订阅的时候不再采用subscribe
而是利用drive
去订阅, 其中当Observable
产生error
事件的时候,driver
不能订阅error
事件,而是以发送信号的形式,把onErrorJustReturn
的值执行到订阅的回调里面去;
func testDriver() { let driver = textField.rx.text.asDriver().skip(1).flatMap {[weak self] (text) -> Driver<String> in guard let `self` = self else { return Observable.just("").asDriver(onErrorJustReturn: "drive error") } return self.dealwithData(inputText: text ?? "").asDriver(onErrorJustReturn: "drive error") } driver.drive { (result) in Logger("第一次订阅 \(result) - 线程 - \(Thread.current)") } onCompleted: { Logger("onCompleted") } onDisposed: { Logger("onDisposed") }.disposed(by: disposeBag) driver.drive { (result) in Logger("第二次订阅 \(result) - 线程 - \(Thread.current)") } onCompleted: { Logger("onCompleted") } onDisposed: { Logger("onDisposed") }.disposed(by: disposeBag) }
运行结果:
Log - 开始模拟发起请求 当前线程 - <NSThread: 0x600001dd8a00>{number = 1, name = main} Log - 第一次订阅 已经输入: 21 - 线程 - <NSThread: 0x600001dd8a00>{number = 1, name = main} Log - 第二次订阅 已经输入: 21 - 线程 - <NSThread: 0x600001dd8a00>{number = 1, name = main}
通过结果可以看到满足我们的需求并和上述结果一致;最后再来看下面这一段代码,实际上会发现driver
的作用和observe(on: MainScheduler.instance).catchAndReturn(-1).share(replay: 1, scope: .whileConnected)
是等价的;
let observable = Observable.just(1) observable.observe(on: MainScheduler.instance).catchAndReturn(-1).share(replay: 1, scope: .whileConnected) //等价 observable.asDriver(onErrorJustReturn: -1)