RxSwift 的那些事
2018-12-01 本文已影响21人
Lin__Chuan
观察者模式
被观察者给观察者(订阅者)发送消息(通知), 观察者接收消息, 做相应的处理.
比如妈妈照顾宝宝, 妈妈是观察者, 宝宝是被观察者.
只要被观察者发出了某些事件比如宝宝哭声, 通知到订阅者, 订阅者就会相应处理.
观察者模式的使用
在 App 架构中, View 层的展示依赖于 Model层数据的更新.
反馈回路
在观察者模式中有几种常用到的技术
- Notification
Notification 将值从单一源广播给若干个收听者. - KVO
键值监听可以将某个对象上属性的改变报告给另一个对象 - 响应式编程
响应式编程也是一种用来交流变更的工具, 不过和通知或者 KVO 不同的是, 它专注于在源和目标之间的变更, 让逻辑可以在部件之间传输信息的同时得以表达. 这是一种单向绑定.
macOS 上的 Cocoa 包含 Cocoa 绑定技术, 它是一种双向绑定. 在一个方向上建立连接, 在反方向上也建立连接.
在上一篇文章中介绍了KVO的本质, 今天这里主要涉及的是响应式编程中, ReactiveX 的 Swift 实现 RxSwift.
RxSwift 能做什么?
-
1. Target Action
用 Rx 实现 button 点击
button.rx.tap
.subscribe(onNext: {
print("button Tapped")
})
.disposed(by: disposeBag)
-
2. 代理
用 Rx 实现滚动事件代理
scrollView.rx.contentOffset
.subscribe(onNext: { contentOffset in
print("contentOffset: \(contentOffset)")
})
.disposed(by: disposeBag)
- 3. 闭包回调
URLSession.shared.rx.data(request: URLRequest(url: url))
.subscribe(onNext: { data in
print("Data Task Success with count: \(data.count)")
}, onError: { error in
print("Data Task Error: \(error)")
})
.disposed(by: disposeBag)
- 通知
NotificationCenter.default.rx
.notification(.UIApplicationWillEnterForeground)
.subscribe(onNext: { (notification) in
print("Application Will Enter Foreground")
})
.disposed(by: disposeBag)
- 5. KVO
user.rx.observe(String.self, #keyPath(User.name))
.subscribe(onNext: { newValue in
print("do something with newValue")
})
.disposed(by: disposeBag)
-
6. 处理多个任务之间依赖关系
例如, 先通过用户名密码取得 Token 然后通过 Token 取得用户信息.
/// 用 Rx 封装接口
enum Api {
/// 通过用户名密码取得一个 token
static func token(username: String, password: String) -> Observable<String> { ... }
/// 通过 token 取得用户信息
static func userInfo(token: String) -> Observable<UserInfo> { ... }
}
/// 通过用户名和密码获取用户信息
Api.token(username: "beeth0ven", password: "987654321")
.flatMapLatest(Api.userInfo)
.subscribe(onNext: { userInfo in
print("获取用户信息成功: \(userInfo)")
}, onError: { error in
print("获取用户信息失败: \(error)")
})
.disposed(by: disposeBag)
-
7. 等待多个并发任务完成后处理结果
例如, 需要将两个网络请求合并成一个.
/// 用 Rx 封装接口
enum Api {
/// 取得老师的详细信息
static func teacher(teacherId: Int) -> Observable<Teacher> { ... }
/// 取得老师的评论
static func teacherComments(teacherId: Int) -> Observable<[Comment]> { ... }
}
/// 同时取得老师信息和老师评论
Observable.zip(
Api.teacher(teacherId: teacherId),
Api.teacherComments(teacherId: teacherId)
).subscribe(onNext: { (teacher, comments) in
print("获取老师信息成功: \(teacher)")
print("获取老师评论成功: \(comments.count) 条")
}, onError: { error in
print("获取老师信息或评论失败: \(error)")
})
.disposed(by: disposeBag)
更多的使用可以查看官方Demo.
从上面的例子可以看到, RxSwift 的使用可以简化代码, 不过我个人建议不要滥用, 因为对于不用 RxSwift 的人来说, 代码可读性较差了.
RxSwift 中有非常多的操作符, 用于应对各种不同的情况, 详情可以查看 RxSwift 中的操作符
作为一个响应式编程的基础框架, RxSwift 除了可以在常规 MVC 架构的程序中使用外, 它最大的用武之地在于 MVVM, RxFeedback, Reactkit.
- MVVM - 当今非常流行的 MVVM 设计模式
- RxFeedback - 由 RxSwift 创始人(Krunoslav Zaher) 提供的一个反馈循环架构
- ReactorKit - 结合了 Flux 和响应式编程的架构.
RxSwift 核心
-
Observable: 可被监听的序列, 用来产生事件.
所有的事物都是序列,Observable
可以用于描述元素异步产生的序列. -
Observer - 观察者, 用来响应事件.
响应事件的都是观察者(订阅者), 对事件做出不同的处理. -
Operator - 创建变化组合事件
观察者通过Operator
对事件做出不同的处理. -
Disposable - 管理绑定(订阅)的生命周期
- 一般一个序列如果发出了
error
或者completed
事件, 那么所有内部资源都会被释放. - 可以对返回的可被清除的资源(Disposable) 调用
dispose
方法, 提前释放这些资源或取消订阅.
- 一般一个序列如果发出了
-
Schedulers - 线程队列调配
用于控制任务在哪个线程或队列运行.
// 创建被观察者
// Observable<String>
let text = usernameOutlet.rx.text.orEmpty.asObservable()
// Observable<Bool>
let passwordValid = text
// Operator 创建一个新的事件, 密码长度大于minimalUsernameLength
.map { $0.characters.count >= minimalUsernameLength }
// Observer<Bool>
let observer = passwordValidOutlet.rx.isHidden
// Disposable
let disposable = passwordValid
// Scheduler 用于控制任务在那个线程队列运行
.subscribeOn(MainScheduler.instance)
.observeOn(MainScheduler.instance)
.bind(to: observer)
...
// 取消绑定,你可以在退出页面时取消绑定
disposable.dispose()
RxSwift 的源码解读
这才是本片最大的重点.