RxSwift处理分页数据请求

Based on the examples provided with in the RxSwift GitHub repo I managed to do it.
Basically, I'm using a recursive function that returns my stream of PaginatedList items, it calls itself with the loadNextPage trigger for the next page. Here the code I used in my API manager:

class func films(withTitle title: String, startingAtPage page: Int = 0, loadNextPageTrigger trigger: Observable<Void> = Observable.empty()) -> Observable<[Film]> {
    let parameters: FilmSearchParameters = FilmSearchParameters(query: title, atPage: page)
    return TMDbAPI.instance.films(fromList: [], with: parameters, loadNextPageTrigger: trigger)
}

fileprivate func films(fromList currentList: [Film], with parameters: FilmSearchParameters, loadNextPageTrigger trigger: Observable<Void>) -> Observable<[Film]> {

    return self.films(with: parameters).flatMap { (paginatedList) -> Observable<[Film]> in
        let newList = currentList + paginatedList.results
        if let _ = paginatedList.nextPage {
            return [
                Observable.just(newList),
                Observable.never().takeUntil(trigger),
                self.films(fromList: newList, with: parameters.nextPage, loadNextPageTrigger: trigger)
            ].concat()
        } else { return Observable.just(newList) }
    }
}

fileprivate func films(with parameters: FilmSearchParameters) -> Observable<PaginatedList<Film>> {
    guard !parameters.query.isEmpty else { return Observable.just(PaginatedList.Empty()) }
    return Observable<PaginatedList<Film>>.create { (observer) -> Disposable in
        let request = Alamofire
            .request(Router.searchFilms(parameters: parameters))
            .validate()
            .responsePaginatedFilms(queue: nil, completionHandler: { (response) in
                switch response.result {
                case .success(let paginatedList):
                    observer.onNext(paginatedList)
                    observer.onCompleted()
                case .failure(let error):
                    observer.onError(error)
                }
            })
        return Disposables.create { request.cancel() }
    }
}

In ViewModel

fileprivate func setupFilms() -> Observable<[Film]> {

    let trigger = self.nextPageTrigger.asObservable().debounce(0.2, scheduler: MainScheduler.instance)

    return self.textSearchTrigger
        .asObservable()
        .debounce(0.3, scheduler: MainScheduler.instance)
        .distinctUntilChanged()
        .flatMapLatest { (query) -> Observable<[Film]> in
            return TMDbAPI.films(withTitle: query, loadNextPageTrigger: trigger)
        }
        .shareReplay(1)
}
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容