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)


相关文章
@PathVariable注解的作用
1.@PathVariable注解的作用 在SpringMVC中可以使用占位符进行参数绑定,地址/list/1/3可以写成/list/{page}/{limit},占位符{page}和{limit}对应的值就是1和3。在业务方法中我们可以使用@PathVariable注解进行占位符的匹配获取工作。
2171 0
|
3月前
|
缓存 运维 安全
WordPress安全加速:Cloudflare + Nginx缓存优化方案
本文介绍如何通过Cloudflare与Nginx优化WordPress网站性能,涵盖静态资源长期缓存、动态页面智能缓存及敏感路径保护,提升加载速度并保障后台安全。适用于使用Cloudflare与Nginx环境的WordPress站点。
124 0
|
11月前
|
存储 机器学习/深度学习 PyTorch
【AI系统】推理文件格式
本文介绍了神经网络模型的序列化与反序列化技术,涵盖跨平台通用序列化方法(如 Protobuf 和 FlatBuffers)、模型自定义序列化方法、语言级通用序列化方法等,重点讨论了这两种流行文件格式的特点、使用场景及其在模型部署中的作用。
230 1
【AI系统】推理文件格式
|
11月前
|
算法 Java 测试技术
使用 BenchmarkDotNet 对 .NET 代码进行性能基准测试
使用 BenchmarkDotNet 对 .NET 代码进行性能基准测试
246 13
|
Rust JavaScript Java
后端使用的语言是什么?
【10月更文挑战第12天】后端使用的语言是什么?
793 14
|
程序员 UED iOS开发
SVProgressHUD和MBProgressHUD的优缺点与SVProgressHUD震动实现
SVProgressHUD和MBProgressHUD的优缺点与SVProgressHUD震动实现
624 0
|
监控 Linux
CentOS7中使用一键脚本部署Librenms网络监控系统
CentOS7中使用一键脚本部署Librenms网络监控系统
603 1
|
Web App开发 编解码 移动开发
现代前端开发中的响应式设计与跨平台兼容性
在当今互联网应用程序的快速发展中,响应式设计和跨平台兼容性已经成为前端开发中至关重要的技术策略。本文将探讨响应式设计的基本原则和实现方法,以及如何通过最新的前端技术实现在不同设备和平台上的一致性用户体验。
|
开发者 iOS开发
no identity found Command CodeSign failed with a nonzero exit code
no identity found Command CodeSign failed with a nonzero exit code
629 0
|
存储
RxSwift+MVVM项目实战-单分组UITableView添加、删除、移动功能
RxSwift+MVVM项目实战-单分组UITableView添加、删除、移动功能
306 0
下一篇
开通oss服务