0

鉴于我的应用程序将从服务器下载文件,而我只希望同时进行 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)为这些不同的项目多次调用 (progress) 块(每个项目都有不同的进度信息,导致 UI 表现得有点奇怪)。

如何确保下载一个一个而不是同时完成?

4

1 回答 1

0

alamofireManager().rx.download()是同时下载还是串行下载?

我不确定它是怎么做的,所以先测试一下。隔离此代码并查看它是否一次执行多个下载。如果是这样,请阅读有关串行下载而不是并发下载的文档。

如果它一次下载一个,则意味着它与触发进度条更新问题的 Rx 代码有关。如果它一次不下载一个,那么这意味着我们只需要阅读 Alamofire 的文档,了解如何一次下载一个。

复杂的转换和副作用

需要考虑的是,您的数据流变得越来越复杂且难以调试,因为一个流中发生了很多事情。由于有多个平面地图,可能会有更多排放影响进度条更新。获取 Observable 的大量平面地图操作也可能是导致进度条更新多次触发的原因。

复杂的数据流

在一个数据流中,您 (a) 执行了网络调用 (b) 更新了进度条 (c) 过滤完成的视频 (d) 并通过在开始时使用 flatMapWithIndex 将 id 和视频模型配对在一起返回到您想要的视频这样您就可以在最后返回模型。有点复杂......我的猜测是奇怪的进度条更新可能是由创建一个热可观察的 on call 引起的$0.rx.progress()

我为我的 Rx Playground 制作了一个github 要点,它试图模拟你正在尝试做的事情。

在函数式反应式编程中,如果您首先定义数据流/可观察对象,它将更具可读性和更容易调试。在我的主旨中,我从 observables 以及我计划如何为下载进度建模开始。

如果 RxA​​lamofire 查询一次下载 1 个,此代码将避免并发问题,并且它正确显示了 a 的进度值UIProgressBar

边注

您是否需要跟踪每个下载项目的单个下载进度?或者你想让你的进度条只增加每个完成的下载项目?

此外,请注意误用多个 flatMap 链的可能危险,如此处所述

于 2016-11-14T08:49:13.517 回答