I can't manage to get this solution to work: https://github.com/liuznsn/RxMoyaPaginationNetworking
Maybe someone can tell me where is the mistake. The loading variable never goes to false. I guess the issue is in the request observable, but I can't find out why.
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()
}
The problem is here:
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 doesn't emit a value until after loadData returns. The way your code is structured, emitting a signal on the refreshTrigger
will start the network request, and then set loading to true after the network request completes.
It would be better to have refreshRequest
and nextPageRequest
return an Observable of what page to load and then merge them and call flatMap
with the network call on the merged result.