我正在使用RxSwift进行刷新和刷新下一页。
目前,这是我目前工作的viewModel:
public final class MomentViewModel {
// Property
let refreshTrigger = PublishSubject<Void>()
let loadNextPageTrigger = PublishSubject<Void>()
let loading = Variable<Bool>(false)
let posts = Variable<[Post]>([])
var pageIndex: Int = 0
let error = PublishSubject<Swift.Error>()
private let disposeBag = DisposeBag()
public init() {
let refreshRequest = loading.asObservable()
.sample(refreshTrigger)
.flatMap { loading -> Observable<Int> in
if loading {
return Observable.empty()
} else {
return Observable<Int>.create { observer in
self.pageIndex = 0
print("reset page index to 0")
observer.onNext(0)
observer.onCompleted()
return Disposables.create()
}
}
}
.debug("refreshRequest", trimOutput: false)
let nextPageRequest = loading.asObservable()
.sample(loadNextPageTrigger)
.flatMap { loading -> Observable<Int> in
if loading {
return Observable.empty()
} else {
return Observable<Int>.create { [unowned self] observer in
self.pageIndex += 1
print(self.pageIndex)
observer.onNext(self.pageIndex)
observer.onCompleted()
return Disposables.create()
}
}
}
.debug("nextPageRequest", trimOutput: false)
let request = Observable.merge(refreshRequest, nextPageRequest)
.debug("Request", trimOutput: false)
let response = request.flatMapLatest { page in
RxAPIProvider.shared.getPostList(page: page).materialize()
}
.share(replay: 1)
.elements()
.debug("Response", trimOutput: false)
Observable
.combineLatest(request, response, posts.asObservable()) { request, response, posts in
return self.pageIndex == 0 ? response : posts + response
}
.sample(response)
.bind(to: posts)
.disposed(by: disposeBag)
Observable
.merge(request.map{ _ in true },
response.map { _ in false },
error.map { _ in false })
.bind(to: loading)
.disposed(by: disposeBag)
}
}
refreshTrigger
和loadNextPageTrigger
绑定到不同的目标赞:
self.tableView.rx_reachedBottom
.map { _ in () }
.bind(to: self.viewModel.loadNextPageTrigger)
.disposed(by: disposeBag)
self.refreshControl.rx.controlEvent(.valueChanged)
.bind(to: self.viewModel.refreshTrigger)
.disposed(by: disposeBag)
self.rx.sentMessage(#selector(UIViewController.viewWillAppear(_:)))
.map { _ in () }
.bind(to: viewModel.refreshTrigger)
.disposed(by: disposeBag)
问题:
当我将tableView滚动到底部并触发loadNextPageTrigger
时,一切正常。
但是,如果下一个请求中没有更多数据,将无限触发loadnextPageTrigger。 任何帮助将不胜感激。
您可以在此处下载Demo。
答案 0 :(得分:1)
主要思想是检查是否所有元素都已加载。我在源代码中发现你加载了20个部分,所以这个条件应该可以正常if loadedPosts < 20 then stop loading new part
。在这里,我与您分享您可以根据需要重构的基本解决方案(因为我不擅长RxSwift
):
在MomentViewModel
中,您应声明属性
private var isAllLoaded = false
如果加载了所有值,则设置为true。然后,您应该检查响应设置正确[Post]
的每个isAllLoaded
:
Observable
.combineLatest(request, response, posts.asObservable()) { request, response, posts in
self.isAllLoaded = response.count < 20 // here the check
return self.pageIndex == 0 ? response : posts + response
}
.sample(response)
.bind(to: posts)
.disposed(by: disposeBag)
然后在nextPageRequest
中,如果所有部分都已加载,则应返回.empty()
观察者:
if loading {
return Observable.empty()
} else {
guard !self.isAllLoaded else { return Observable.empty() }
return Observable<Int>.create { [unowned self] observer in
self.pageIndex += 1
print(self.pageIndex)
observer.onNext(self.pageIndex)
observer.onCompleted()
return Disposables.create()
}
}
P.S。要复制/粘贴的MomentViewModel.swift
文件。