鉴于我的应用程序将从服务器下载文件而我只希望 1下载同时进行,那么如何使用RxAlamofire
完成此操作?我可能只是错过了一个Rx运算符。
这是粗略的代码:
Observable
.from(paths)
.flatMapWithIndex({ (ip, idx) -> Observable<(Int, Video)> in
let v = self.files![ip.row] as! Video
return Observable.from([(idx, v)])
})
.flatMap { (item) -> Observable<Video> in
let req = URLRequest(url: item.1.downloadURL())
return Api.alamofireManager()
.rx
.download(req, to: { (url, response) -> (destinationURL: URL, options: DownloadRequest.DownloadOptions) in
...
})
.flatMap({ $0.rx.progress() })
.flatMap { (progress) -> Observable<Float> in
// Update a progress bar
...
}
// Only propagate finished items
.filter { $0 >= 1.0 }
// Return the item itself
.flatMap { _ in Observable.from([item.1]) }
}
.subscribe(
onNext: { (res) in
...
},
onError: { (error) in
...
},
onCompleted: {
...
}
)
我的问题是 a) RxAlamofire会同时下载多个项目, b)(进度)块会多次调用这些不同的项目(不同的每个进展信息,导致用户界面表现得有点奇怪)。
如何确保逐个下载而不是同时进行下载?
答案 0 :(得分:0)
alamofireManager().rx.download()
是同时还是连续下载?我不确定它是怎么做的,所以先测试一下。隔离此代码并查看它是否一次执行多个下载。如果是,请阅读有关串行下载而不是并发下载的文档。
如果一次下载一个,则表示它与您的Rx代码有关,触发了进度条更新问题。如果它不能一次下载一个,那么这意味着我们只需要阅读Alamofire的文档,了解如何一次下载一个。
需要考虑的是,您的数据流变得越来越复杂,难以调试,因为在一个流中发生了很多事情。由于多个平面地图,可能会有更多的排放影响进度条更新。获取Observable的众多平面地图操作也可能是进度条上多次触发更新的原因。
在一个数据流中,您(a)执行网络呼叫(b)更新进度条(c)过滤完成的视频(d)并在开始时使用flatMapWithIndex返回到您想要的视频以将ID和视频模型,以便您可以在最后返回模型。有点复杂......我的猜测是,通过调用$0.rx.progress()
创建一个热观察,可能会导致奇怪的进度条更新。
我制作了一个github gist我的Rx Playground,试图模拟你想要做的事情。
在功能性反应式编程中,如果首先定义数据流/可观察量,它将更易读,更容易调试。在我的要点中,我从观察者开始,以及我计划如何建模下载进度。
如果RxAlamofire查询一次下载1个,并且它正确显示UIProgressBar
的进度值,此代码将避免并发问题。
您是否需要跟踪每个下载项目的个人进度下载量?或者您希望您的进度条只是按完成的下载项递增?
另外,要注意滥用多个flatMaps as explained here链的可能危险。