繁体   English   中英

使用RxJava + Retrofit对列表中的每个项目进行API请求

[英]Using RxJava + Retrofit to make API requests for each item in a list

我试图通过将多个改造API调用链接在一起来创建一个可观察的对象。 这些步骤是:

  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);

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

编辑:删除了Observable.create,改造已经为您制作了一个可观察对象,您只需要对其进行转换。

编辑2:您也不需要对Subscriber.onError进行任何操作,如果抛出错误,它将自行调用Subscriber.onError。

很好,不确定您为什么选择可观察的平面图。 我宁愿将平面图制作为Observable :: from,也值得添加。 基本上,我将把一件事映射到多个对象,然后执行一些操作,将多个对象放回一个对象,一旦我收集了所有发出的项目,就订阅该对象。

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});

我认为类似这样的方法应该对您有用。 无需拉入Subject来将其发送DownloadedFile(s),您只需使用REST服务中的Observable即可映射到每个DownloadedFiles:

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。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM