- 首先我們創(chuàng)建一個:
序列的中的序列 - string - 映射 - 序列,并且發(fā)起多次訂閱,如下代碼:
//創(chuàng)建序列
let result = inputTF.rx.text.skip(1)
.flatMap { [weak self](input) -> Observable<Any> in
return (self?.dealwithData(inputText:input ?? ""))!
}
//連續(xù)訂閱兩次
result.subscribe(onNext: { (element) in
print("訂閱到了--:\(element)")
})
result.subscribe(onNext: { (element) in
print("訂閱到了--:\(element)---\(Thread.current)")
})
//模擬網(wǎng)絡(luò)請求
func dealwithData(inputText:String)-> Observable<Any>{
print("請求網(wǎng)絡(luò)了 \(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("發(fā)送之前看看: \(Thread.current)")
ob.onNext("已經(jīng)輸入:\(inputText)")
ob.onCompleted()
}
return Disposables.create()
})
運行代碼,并在inputTF輸入內(nèi)容1,打印如下:
請求網(wǎng)絡(luò)了 <NSThread: 0x600000063b40>{number = 1, name = main}
發(fā)送之前看看: <NSThread: 0x604000269600>{number = 4, name = (null)}
請求網(wǎng)絡(luò)了 <NSThread: 0x600000063b40>{number = 1, name = main}
訂閱到了--:已經(jīng)輸入:1
發(fā)送之前看看: <NSThread: 0x604000463c80>{number = 5, name = (null)}
訂閱到了--:已經(jīng)輸入:1---<NSThread: 0x604000463c80>{number = 5, name = (null)}
輸入內(nèi)容1234, 打印error如下:
請求網(wǎng)絡(luò)了 <NSThread: 0x600000063b40>{number = 1, name = main}
Unhandled error happened: Error Domain=com.lgcooci.cn Code=10086 "(null)"
subscription called from:
發(fā)送之前看看: <NSThread: 0x604000462040>{number = 7, name = (null)}
請求網(wǎng)絡(luò)了 <NSThread: 0x600000063b40>{number = 1, name = main}
Unhandled error happened: Error Domain=com.lgcooci.cn Code=10086 "(null)"
subscription called from:
發(fā)送之前看看: <NSThread: 0x6000004798c0>{number = 6, name = (null)}
從上面的打印可以看出:
- 多次訂閱就會多次請求,
浪費網(wǎng)絡(luò) - 數(shù)據(jù)請求回來以后還在是
子線程 - 多次執(zhí)行錯誤事件
解決方法:
- 開啟網(wǎng)絡(luò)共享
.share(replay: 1, scope: .whileConnected)
- 切換到主線程跟新UI
.observeOn(MainScheduler())
3.檢測錯誤事件(不會反悔error,導(dǎo)致崩潰)
.catchErrorJustReturn("檢測到了錯誤事件")
- 完整代碼:
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)
- 執(zhí)行結(jié)果如下:
----------輸入1:
請求網(wǎng)絡(luò)了 <NSThread: 0x604000078d00>{number = 1, name = main}
發(fā)送之前看看: <NSThread: 0x604000473200>{number = 5, name = (null)}
訂閱到了--:已經(jīng)輸入:1
訂閱到了--:已經(jīng)輸入:1---<NSThread: 0x604000078d00>{number = 1, name = main}
----------輸入1234:
請求網(wǎng)絡(luò)了 <NSThread: 0x604000078d00>{number = 1, name = main}
訂閱到了--:檢測到了錯誤事件
訂閱到了--:檢測到了錯誤事件---<NSThread: 0x604000078d00>{number = 1, name = main}
發(fā)送之前看看: <NSThread: 0x60000066d2c0>{number = 6, name = (null)}
上面的問題雖然解決了,但是:
- 我們修改了很多代碼,那有沒有更好的解決方案呢
- 這時候就該我們的老司機
Driver出場了
Driver 的簡單使用
- 網(wǎng)絡(luò)共享
- 綁定到了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())
執(zhí)行代碼打印如下:
圖片.png
Driver 源碼解析
asDriver是ControlProperty的擴展方法,返回一個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>
- 網(wǎng)絡(luò)共享:
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內(nèi)部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進行線程調(diào)度catchErrorJustReturn(onErrorJustReturn)錯誤處理
extension ObservableConvertibleType {
...
public func asDriver(onErrorJustReturn: Element) -> Driver<Element> {
let source = self
.asObservable()
.observeOn(DriverSharingStrategy.scheduler)
.catchErrorJustReturn(onErrorJustReturn)
return Driver(source)
}
...
}
