RxSwift 分页
Posted
技术标签:
【中文标题】RxSwift 分页【英文标题】:RxSwift pagination 【发布时间】:2017-04-15 07:48:40 【问题描述】:我无法让这个解决方案发挥作用: https://github.com/liuznsn/RxMoyaPaginationNetworking
也许有人可以告诉我错误在哪里。加载变量永远不会变为假。我猜问题出在可观察的请求中,但我找不到原因。
class PaginationNetworkModel<T1: Mappable>: NSObject
let refreshTrigger = PublishSubject<Void>()
let loadNextPageTrigger = PublishSubject<Void>()
let loading = Variable<Bool>(false)
let elements = Variable<[T1]>([])
var offset:Int = 0
let error = PublishSubject<Swift.Error>()
private let disposeBag = DisposeBag()
override init()
super.init()
let refreshRequest = loading.asObservable()
.sample(refreshTrigger)
.flatMap [unowned self] loading -> Observable<[T1]> in
if loading
return Observable.empty()
else
return self.loadData(offset: self.offset)
let nextPageRequest = loading.asObservable()
.sample(loadNextPageTrigger)
.flatMap [unowned self] loading -> Observable<[T1]> in
if loading
return Observable.empty()
else
self.offset += 1
return self.loadData(offset: self.offset)
let request = Observable
.of(refreshRequest, nextPageRequest)
.merge()
.shareReplay(1)
let response = request.flatMap events -> Observable<[T1]> in
request
.do(onError: error in
self.error.onNext(error)
).catchError( error -> Observable<[T1]> in
Observable.empty()
)
.shareReplay(1)
Observable
.combineLatest(request, response, elements.asObservable()) [unowned self] request, response, elements in
return self.offset == 0 ? response : elements + response
.sample(response)
.bind(to: elements)
.addDisposableTo(rx_disposeBag)
Observable
.of(request.map _ in true ,
response.map $0.count == 0 ,
error.map _ in false
)
.merge()
.bind(to: loading)
.addDisposableTo(rx_disposeBag)
func loadData(offset: Int) -> Observable<[T1]>
return Observable.empty()
【问题讨论】:
您是否意识到您的loadData
函数永远不会返回任何数据,这意味着response
永远不会触发?
是的。如您所见,它是通用类,如果我需要其他服务器方法,我将继承该类。我确定响应会触发,即如果我将 request.map 设置为 false 我将从服务器获取所有对象,但没有“加载”功能。
由于某种原因 request.map 在 response.map 之后调用,其中设置为 false,并立即设置为 true 因为请求,但我看不到它在响应后调用的位置
【参考方案1】:
感谢丹尼尔的帮助,这里完成了解决方案
调用示例:
goodsModel = GoodsNetworkModel()
goodsModel.elements.asObservable().bind(to: tableView.rx.items(cellIdentifier: "Cell", cellType: StoreCell.self)) (ip, item: Goods, cell: StoreCell) in
cell.configure(goods: item)
.addDisposableTo(rx_disposeBag)
tableView.rx.itemSelected.bind() [unowned self] ip in
self.didSelectRow(ip: ip.row)
.addDisposableTo(rx_disposeBag)
rx.sentMessage(#selector(UIViewController.viewDidAppear(_:)))
.map _ in ()
.bind(to: goodsModel.refreshTrigger)
.addDisposableTo(rx_disposeBag)
tableView.rx_reachedBottom
.map _ in ()
.bind(to: goodsModel.loadNextPageTrigger)
.addDisposableTo(rx_disposeBag)
型号代码:
class PaginationNetworkModel<T1: Mappable>: NSObject
let refreshTrigger = PublishSubject<Void>()
let loadNextPageTrigger = PublishSubject<Void>()
let loading = Variable<Bool>(false)
let elements = Variable<[T1]>([])
var offset:Int = 0
let error = PublishSubject<Swift.Error>()
private let disposeBag = DisposeBag()
override init()
super.init()
let refreshRequest = loading.asObservable()
.sample(refreshTrigger)
.flatMap loading -> Observable<Int> in
if loading
return Observable.empty()
else
return Observable<Int>.create observer in
observer.onNext(0)
observer.onCompleted()
return Disposables.create()
let nextPageRequest = loading.asObservable()
.sample(loadNextPageTrigger)
.flatMap [unowned self] loading -> Observable<Int> in
if loading
return Observable.empty()
else
return Observable<Int>.create [unowned self] observer in
self.offset += 1
observer.onNext(self.offset)
observer.onCompleted()
return Disposables.create()
let request = Observable
.of(refreshRequest, nextPageRequest)
.merge()
.shareReplay(1)
let response = request.flatMap offset -> Observable<[T1]> in
self.loadData(offset: offset)
.do(onError: [weak self] error in
self?.error.onNext(error)
).catchError( error -> Observable<[T1]> in
Observable.empty()
)
.shareReplay(1)
Observable
.combineLatest(request, response, elements.asObservable()) [unowned self] request, response, elements in
return self.offset == 0 ? response : elements + response
.sample(response)
.bind(to: elements)
.addDisposableTo(rx_disposeBag)
Observable
.of(request.map_ in true,
response.map $0.count == 0 ,
error.map _ in false )
.merge()
.bind(to: loading)
.addDisposableTo(rx_disposeBag)
func loadData(offset: Int) -> Observable<[T1]>
return Observable.empty()
【讨论】:
如果我创建一个PaginationNetworkModel
然后触发它的loadNextPageTrigger
,模型将尝试加载页面 1 而不会尝试加载页面 0。您确定这是正确的行为吗?
编辑我的答案,所以在调用 loadNextPageTrigger 之前我总是调用 refreshTrigger【参考方案2】:
问题出在这里:
let refreshRequest: Observable<[T1]> = loading.asObservable()
.sample(refreshTrigger)
.flatMap [unowned self] loading -> Observable<[T1]> in
if loading
return Observable.empty()
else
return self.loadData(offset: self.offset)
refreshRequest 在 after loadData 返回之前不会发出值。您的代码的结构方式,在refreshTrigger
上发出信号将启动网络请求,然后在网络请求完成后将 loading 设置为 true。
最好让refreshRequest
和nextPageRequest
返回要加载哪个页面的 Observable,然后合并它们,并在合并结果上通过网络调用调用 flatMap
。
【讨论】:
以上是关于RxSwift 分页的主要内容,如果未能解决你的问题,请参考以下文章