RxSwift 生态系统
RxCocoa 给 UI框架 提供了 支持,让我们能够使用按钮点击序列,输入框当前文本序列等。不过 RxCocoa 也只是 RxSwift 生态系统 中的一员。RxSwift 生态系统 还给其他框架提供了 支持:
- UITableView 和 UICollectionView 数据源
你只需要几行代码就可以布局一个多 Section
的 tabelView
:
Copy let dataSource = RxTableViewSectionedReloadDataSource<SectionModel<String, Int>>()
Observable.just([SectionModel(model: "title", items: [1, 2, 3])])
.bind(to: tableView.rx.items(dataSource: dataSource))
.disposed(by: disposeBag)
Copy let stringURL = ""
// 使用 NSURLSession
let session = NSURLSession.sharedSession()
_ = session.rx
.json(.get, stringURL)
.observeOn(MainScheduler.instance)
.subscribe { print($0) }
// 使用 Alamofire 引擎
_ = json(.get, stringURL)
.observeOn(MainScheduler.instance)
.subscribe { print($0) }
// 使用 Alamofire manager
let manager = Manager.sharedInstance
_ = manager.rx.json(.get, stringURL)
.observeOn(MainScheduler.instance)
.subscribe { print($0) }
// URLHTTPResponse + Validation + String
_ = manager.rx.request(.get, stringURL)
.flatMap {
$0
.validate(statusCode: 200 ..< 300)
.validate(contentType: ["text/json"])
.rx.string()
}
.observeOn(MainScheduler.instance)
.subscribe { print($0) }
监听数据:
Copy let realm = try! Realm()
let laps = realm.objects(Lap.self)
Observable.collection(from: laps)
.map {
laps in "\(laps.count) laps"
}
.subscribe(onNext: { text in
print(text)
})
添加数据:
Copy let realm = try! Realm()
let messages = [Message("hello"), Message("world")]
Observable.from(messages)
.subscribe(realm.rx.add())
删除数据:
Copy let realm = try! Realm()
let messages = realm.objects(Message.self)
Observable.from(messages)
.subscribe(realm.rx.delete())
Android
iOS(RxSwift) 版:
Copy ...
let usernameValid = usernameOutlet.rx.text.orEmpty
.map { $0.characters.count >= minimalUsernameLength }
.share(replay: 1)
let passwordValid = passwordOutlet.rx.text.orEmpty
.map { $0.characters.count >= minimalPasswordLength }
.share(replay: 1)
let everythingValid = Observable
.combineLatest(usernameValid, passwordValid) { $0 && $1 }
.share(replay: 1)
usernameValid
.bind(to: passwordOutlet.rx.isEnabled)
.disposed(by: disposeBag)
usernameValid
.bind(to: usernameValidOutlet.rx.isHidden)
.disposed(by: disposeBag)
passwordValid
.bind(to: passwordValidOutlet.rx.isHidden)
.disposed(by: disposeBag)
everythingValid
.bind(to: doSomethingOutlet.rx.isEnabled)
.disposed(by: disposeBag)
...
Android(RxJava) 版:
Copy ...
final Observable<Boolean> usernameValid = RxTextView.textChanges(usernameEditText)
.map(text -> text.length() >= minimalUsernameLength)
.compose(Rx.shareReplay(1));
final Observable<Boolean> passwordValid = RxTextView.textChanges(usernameEditText)
.map(text -> text.length() >= minimalPasswordLength)
.compose(Rx.shareReplay(1));
final Observable<Boolean> everythingValid = Observable
.combineLatest(usernameValid, passwordValid, (isUsernameValid, isPasswordValid) -> isUsernameValid && isPasswordValid)
.compose(Rx.shareReplay(1));
disposables.add(usernameValid
.subscribe(RxView.enabled(passwordEditText)));
disposables.add(usernameValid
.subscribe(RxView.visibility(usernameValidTextView)));
disposables.add(passwordValid
.subscribe(RxView.visibility(passwordValidTextView)));
disposables.add(everythingValid
.subscribe(RxView.enabled(doSomethingButton)));
...
这两段代码的逻辑是一样的,一个是 iOS(RxSwift) 版本,另一个是 Android(RxJava) 版本。仔细对比以后,你会发现它们的书写方式都是差不多的。
这样一来,你就可以用同一套逻辑来写跨平台应用,而且这个应用是纯原生的。这不仅节省了开发时间 ,而且还提升了 App 的质量 。
Web 前端
Copy var $input = $('#input'),
$results = $('#results');
Rx.Observable.fromEvent($input, 'keyup')
.map(e => e.target.value)
.filter(text => text.length > 2)
.throttle(500 /* ms */);
.distinctUntilChanged();
.flatMapLatest(searchWikipedia);
.subscribe(data => {
var res = data[1];
$results.empty();
$.each(res, (_, value) => $('<li>' + value + '</li>').appendTo($results));
}, error => {
$results.empty();
$('<li>Error: ' + error + '</li>').appendTo($results);
});
当用户输入一个稳定的关键字后,向维基百科请求搜索结果,然后显示出来。
总结