6

我试图通过将多个改造 api 调用链接在一起来创建一个 observable。步骤是:

  1. 使用 api 调用获取 json 对象列表
  2. 对于列表中的每个对象,进行另一个 api 调用以获取有关该项目的更多详细信息
  3. 将从这个新的详细对象获取的数据写入磁盘上的文件(列表中的每个项目都会发生这种情况)
  4. 最后返回一个单独对象的可观察对象,该对象要求为之前的每个对象创建一个文件

这是我到目前为止所拥有的:

public static Observable<DownloadedFiles> downloadFiles() {
    DownloadedFiles downloadedFiles = new DownloadedFiles();
    Observable.create(subscriber -> {
        return getRestService().getObjectList()
        .flatMapIterable(objects -> objects)
        .flatMap(objectLimited -> getRestService().getObject(objectLimited.getPath()))
        .doOnNext(objectFull -> {

            try {
                File file = new File();
                // Extract data from objectFull and write new file to disk
                // ...
                } catch (IOException e) {
                subscriber.onError(e);
            }

            downloadedFiles.putFile(file);
        })
        .toList()
        .map(objects -> downloadedFiles)
        .finallyDo(() -> {
            subscriber.onNext(downloadedFiles);
            subscriber.onCompleted();
        });
    });
}

@GET("/api/...")
Observable<List<Object>> getObjectList();

@GET("/api/.../{path}")
Observable<Object> getObject(@Path("path") String path);

有人可以确认我使用了正确的运算符。谢谢 。

4

2 回答 2

2

编辑:删除了 Observable.create,改造已经为你制作了一个 observable,你只需要转换它。

编辑2:您也不应该对subscriber.onError 做任何事情,如果抛出错误,它将自行调用subscriber.onError。

很好,不知道你为什么要使用 flatmap observable。我会改为对 Observable::from 进行平面映射,收集也值得添加。基本上,我要将 1 个事物映射到多个事物,然后执行一些操作,将多个事物收集回一个事物,然后在我收集到所有发出的项目后订阅该事物。

public static Observable<DownloadedFiles> downloadFiles() {        
        return getRestService().getObjectList()
        .flatMap(Observable::from)
        .flatMap(objectLimited -> getRestService().getObject(objectLimited.getPath()))
        .doOnNext(objectFull -> {
            try {
                File file = new File();
                // Extract data from objectFull and write new file to disk
                // ...
            } catch (IOException e) {
                new IOException(e);
            }})
      .collect(() -> new DownloadFiles<>(), (files, object) -> {  files.add(object});
于 2015-04-19T17:01:30.720 回答
0

我认为像这样的一些应该适合你。您可以使用 REST 服务中的 Observable 映射到每个 DownloadedFile,而不是拉入 Subject 以将其发送到 DownloadedFile(s):

public static Observable<DownloadedFile> downloadFiles() {
    final Observable<Observable<FullObject>> observable =  getRestService().getObjectList()
            .flatMapIterable(objects -> objects)
            .map(objectLimited -> getRestService().getObject(objectLimited.getPath()));

    return  Observable.mergeDelayError(observable)
            .map(fullObject -> {
                try {
                    File file = new File("path");
                    // Extract data from objectFull and write new file to disk
                    // ...

                    return new DownloadedFile();
                } catch (IOException e) {
                    throw OnErrorThrowable.from(OnErrorThrowable.addValueAsLastCause(e, fullObject));
                }
            });
}

如果您想在传播任何错误之前发出成功保存的文件,您可能需要考虑使用 mergeDelayError(map()) 而不是 flatMap。

于 2015-04-19T16:47:12.977 回答