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)


相关文章
|
10月前
|
数据库
主题域、概念、逻辑、物理四种模型有什么区别与联系?
主题域、概念、逻辑、物理四种模型有什么区别与联系?
|
22天前
|
JavaScript 前端开发 Java
函数形状的定义方式在编程中可以有多种,具体取决于使用的编程语言和上下文。以下是几种常见的定义方式:
函数形状的定义方式在编程中可以有多种,具体取决于使用的编程语言和上下文。以下是几种常见的定义方式:
16 3
|
API Serverless 监控
函数组合的N种方式
随着以函数即服务(Function as a Service)为代表的无服务器计算(Serverless)的广泛使用,很多用户遇到了涉及多个函数的场景,需要组合多个函数来共同完成一个业务目标,这正是微服务“分而治之,合而用之”的精髓所在。
2269 0
|
1月前
|
C++
C++ 接口的实现,及作用通俗理解方式
C++中的接口,一般就是指抽象类,是一种用来描述类对外提供的操作、方法或功能的集合——注意,一般只是描述(声明),而不对这些方法或功能进行定义实现,通常在
35 2
|
1月前
|
算法 编译器 C++
【C++ 概念区分】C++ 中覆盖,重写,隐藏 三者的区别
【C++ 概念区分】C++ 中覆盖,重写,隐藏 三者的区别
43 0
|
1月前
|
存储
通俗解释:Session生成、存储与管理
通俗解释:Session生成、存储与管理
36 0
|
10月前
|
Web App开发 机器人 数据安全/隐私保护
将上下文长度扩展到256k,无限上下文版本的LongLLaMA来了?
将上下文长度扩展到256k,无限上下文版本的LongLLaMA来了?
144 0
|
11月前
|
JavaScript 前端开发
vvue基础指令和基础属性
vue基础指令和基础属性
|
存储 编译器 C语言
C++ 基础篇之类 & 对象的关系
C++ 在 C 语言的基础上增加了面向对象编程,C++ 支持面向对象程序设计。类是 C++ 的核心特性,通常被称为用户定义的类型。
|
消息中间件 存储 运维
函数组合的 N 种模式
随着以函数即服务(Function as a Service)为代表的无服务器计算(Serverless)的广泛使用,很多用户遇到了涉及多个函数的场景,需要组合多个函数来共同完成一个业务目标,这正是微服务“分而治之,合而用之”的精髓所在。本文以阿里云函数计算为例,全面介绍函数组合的常见模式和使用场景,希望有助于选择合适的解决方案。
函数组合的 N 种模式