美文网首页
07.RxSwift 高阶函数(Driver)

07.RxSwift 高阶函数(Driver)

作者: smart_M | 来源:发表于2019-08-25 16:50 被阅读0次
    1. 首先我们创建一个:序列的中的序列 - string - 映射 - 序列,并且发起多次订阅,如下代码:
    //创建序列
    let result  = inputTF.rx.text.skip(1)
                .flatMap { [weak self](input) -> Observable<Any> 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<Any>{
            print("请求网络了 \(Thread.current)") // data
            return Observable<Any>.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,打印如下:

    请求网络了 <NSThread: 0x600000063b40>{number = 1, name = main}
    发送之前看看: <NSThread: 0x604000269600>{number = 4, name = (null)}
    请求网络了 <NSThread: 0x600000063b40>{number = 1, name = main}
    订阅到了--:已经输入:1
    发送之前看看: <NSThread: 0x604000463c80>{number = 5, name = (null)}
    订阅到了--:已经输入:1---<NSThread: 0x604000463c80>{number = 5, name = (null)}
    

    输入内容1234, 打印error如下:

    请求网络了 <NSThread: 0x600000063b40>{number = 1, name = main}
    Unhandled error happened: Error Domain=com.lgcooci.cn Code=10086 "(null)"
     subscription called from:
    
    发送之前看看: <NSThread: 0x604000462040>{number = 7, name = (null)}
    请求网络了 <NSThread: 0x600000063b40>{number = 1, name = main}
    Unhandled error happened: Error Domain=com.lgcooci.cn Code=10086 "(null)"
     subscription called from:
    
    发送之前看看: <NSThread: 0x6000004798c0>{number = 6, name = (null)}
    

    从上面的打印可以看出:

    • 多次订阅就会多次请求,浪费网络
    • 数据请求回来以后还在是 子线程
    • 多次执行错误事件

    解决方法:

    1. 开启网络共享
    .share(replay: 1, scope: .whileConnected)
    
    1. 切换到主线程跟新UI
    .observeOn(MainScheduler())
    

    3.检测错误事件(不会反悔error,导致崩溃)

    .catchErrorJustReturn("检测到了错误事件")
    
    1. 完整代码:
    let result  = inputTF.rx.text.skip(1)
                .flatMap { [weak self](input) -> Observable<Any> in
                    return (self?.dealwithData(inputText:input ?? ""))!
                            .observeOn(MainScheduler())
                            .catchErrorJustReturn("检测到了错误事件")
            }
            .share(replay: 1, scope: .whileConnected)
    
    1. 执行结果如下:
    ----------输入1:
    请求网络了 <NSThread: 0x604000078d00>{number = 1, name = main}
    发送之前看看: <NSThread: 0x604000473200>{number = 5, name = (null)}
    订阅到了--:已经输入:1
    订阅到了--:已经输入:1---<NSThread: 0x604000078d00>{number = 1, name = main}
    
    ----------输入1234:
    请求网络了 <NSThread: 0x604000078d00>{number = 1, name = main}
    订阅到了--:检测到了错误事件
    订阅到了--:检测到了错误事件---<NSThread: 0x604000078d00>{number = 1, name = main}
    发送之前看看: <NSThread: 0x60000066d2c0>{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())
    

    执行代码打印如下:

    图片.png
    Driver 源码解析

    asDriverControlProperty的扩展方法,返回一个Driver对象

    extension ControlProperty {
        public func asDriver() -> Driver<Element> {
            return self.asDriver { _ -> Driver<Element> 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<Element> = SharedSequence<DriverSharingStrategy, Element>
    
    • 网络共享:source.share(replay: 1, scope: .whileConnected)
    public struct DriverSharingStrategy: SharingStrategyProtocol {
        public static var scheduler: SchedulerType { return SharingScheduler.make() }
        public static func share<Element>(_ source: Observable<Element>) -> Observable<Element> {
            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<Element> 中:
    • observeOn(DriverSharingStrategy.scheduler进行线程调度
    • catchErrorJustReturn(onErrorJustReturn)错误处理
    extension ObservableConvertibleType {
        ...
        public func asDriver(onErrorJustReturn: Element) -> Driver<Element> {
            let source = self
                .asObservable()
                .observeOn(DriverSharingStrategy.scheduler)
                .catchErrorJustReturn(onErrorJustReturn)
            return Driver(source)
        }
      ...
    }
    

    相关文章

      网友评论

          本文标题:07.RxSwift 高阶函数(Driver)

          本文链接:https://www.haomeiwen.com/subject/gxohectx.html