RxSwift特征序列Driver的使用,以及共享附加作用与非共享附加作用的区别?

简介: RxSwift特征序列Driver的使用,以及共享附加作用与非共享附加作用的区别?


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)


相关文章
|
5月前
|
JavaScript 前端开发 Java
函数形状的定义方式在编程中可以有多种,具体取决于使用的编程语言和上下文。以下是几种常见的定义方式:
函数形状的定义方式在编程中可以有多种,具体取决于使用的编程语言和上下文。以下是几种常见的定义方式:
41 3
|
3月前
|
算法 网络性能优化
网络中窗口的含义及作用
【8月更文挑战第24天】
78 0
|
3月前
|
安全 前端开发 Java
|
4月前
|
JavaScript
交叉类型的主要用途是表示对象的合成
交叉类型的主要用途是表示对象的合成
27 0
|
6月前
|
C++
C++ 接口的实现,及作用通俗理解方式
C++中的接口,一般就是指抽象类,是一种用来描述类对外提供的操作、方法或功能的集合——注意,一般只是描述(声明),而不对这些方法或功能进行定义实现,通常在
69 2
|
6月前
|
算法 编译器 C++
【C++ 概念区分】C++ 中覆盖,重写,隐藏 三者的区别
【C++ 概念区分】C++ 中覆盖,重写,隐藏 三者的区别
175 0
|
6月前
|
存储
通俗解释:Session生成、存储与管理
通俗解释:Session生成、存储与管理
68 0
|
Web App开发 机器人 数据安全/隐私保护
将上下文长度扩展到256k,无限上下文版本的LongLLaMA来了?
将上下文长度扩展到256k,无限上下文版本的LongLLaMA来了?
171 0
|
JavaScript 前端开发
vvue基础指令和基础属性
vue基础指令和基础属性
|
数据采集 移动开发 数据可视化
空间转录组|Load10X_Spatial函数修改适配多形式数据 + 空转标准流程
空间转录组|Load10X_Spatial函数修改适配多形式数据 + 空转标准流程
636 0