RxJava dependend方法使用async for循环调用

时间:2017-09-27 12:24:41

标签: java android rx-java rx-android

我想用RxJava解决多个dependend调用:

  1. 获取具有尚未上传文件的所有实体
  2. 将文件上传到服务器
  3. 使用收到的网址更新实体
  4. 将实体上传到服务器
  5. 我尝试了不同的方法,但是还没有让它发挥作用。我无法理解如何等待文件上传完成。这是我目前的代码:

    Observable.fromIterable(repository.getFileNotUploaded()) // Returns a list of all entities that should be uploaded to the server
        .flatMap(entity ->
                restService.uploadFile(new File(directory.getPath(), entity.getLocalPath()))
                        .subscribe(fileUrl -> {
                            entity.setFileUrl(fileUrl);
                            repository.update(entity);
                        }));
    // TODO: Wait until all files have been uploaded and the entities have been stored
    // locally. Then upload the list of all entities. 
    

    休息电话:

    public Observable<String> uploadFile(File file) {
    
        return Observable.create(emitter -> {
            AsyncTask.execute(new Runnable() {
                @Override
                public void run() {
                    commClient.sendFileRequest(URL, file,
                            response -> {
                            // ...
                            if(success){
                                    emitter.onNext(new String(response.data));
                            }
    
                                emitter.onComplete();
                            }
                }
            });
        });
    }
    

    此外,我读到在平面地图内调用订阅是一种反模式。如何级联我的方法调用?我应该使用范围方法并返回迭代的当前位置吗?

    编辑 - 感谢Emanuel S的工作解决方案

    伊曼纽尔S的解决方案有效。我还要改变我的休息服务。此服务必须返回Observable<Entity>而不是Observable<String>。另请注意,不应混淆AsyncTask和Rx。

    public Observable<Entity> uploadFile(File file, Entity entity) {
    //...
    entity.setFileUrl(fileUrl);
    emitter.onNext(entity);
    //...
    

1 个答案:

答案 0 :(得分:2)

如果repository.getFileNotUploaded()是一个ArrayList / Collection,你应该使用just和iterate创建你的Observable。

这可能有用(没有经过测试,没有IDE就写了),并将你所有的成员上传到一堆。

正如akarnokd所写,您不需要使用justflatmapIterable,因为您可以使用fromIterable

Observable.just(repository.getFileNotUploaded()).flatMapIterable ( files -> file)
// OR 
Observable.flatmapIterable(repository.getFileNotUploaded())

.flatMap(entity -> rs.uploadFile(new File(yourPath, entity.getLocalPath())) // for each file not uploaded run another observable and return it
.map(entity -> { entity.setFieldUrl(fileUrl); return entity; }) // modify the entity and return it
.toList() // get it back to List<String> with your entities
.flatMap(entityList -> uploadEntityObservable(entityList))
.subscribe( 
    success -> Log.d("Success", "All entities and files uploaded"), 
    error -> Log.e("Error", "error happened somewhere")
);

如果您想通过一次调用上传每个修改过的实体,您可能需要替换

.toList() // get it back to List<String> with your entities
.flatMap(entityList -> uploadEntityObservable(entityList ))

.flatMapIterable( singleEntity -> uploadSingleEntity(singleEntity))

并且不要将asyntask与RxJava混合使用。如果你有RXJava,你不需要AsyncTask。

注意:如果您流式传输数据,并且您的存储库Observable发出数据,则需要使用

repository.getFileNotUploaded() // Observable<Whatever> emit data in a stream.
.flatMapIterable ( files -> file) ...