Android RxJava:当错误被吞没时,上游永远不会完成

Android RxJava:当错误被吞没时,上游永远不会完成,android,kotlin,rx-java,rx-java2,Android,Kotlin,Rx Java,Rx Java2,我正在使用RxJava迭代文件列表,通过网络调用上载每个文件,然后收集成功上载到列表中的文件,并在成功时将这些文件保存在订阅服务器中 此代码有效,但发生错误时除外。其行为应该是记录错误并继续,它会这样做,除非发生错误,订阅者的onSuccess lambda永远不会被调用 观察者是否期望发射的元素数量与原始iterable中相同?我如何跳过错误,并在所有项目都被迭代后完成它?除了Single.never()之外,还有什么东西可以完成不将错误转发到下游的任务吗 queryFiles()?.let

我正在使用RxJava迭代文件列表,通过网络调用上载每个文件,然后收集成功上载到列表中的文件,并在成功时将这些文件保存在订阅服务器中

此代码有效,但发生错误时除外。其行为应该是记录错误并继续,它会这样做,除非发生错误,订阅者的onSuccess lambda永远不会被调用

观察者是否期望发射的元素数量与原始iterable中相同?我如何跳过错误,并在所有项目都被迭代后完成它?除了
Single.never()
之外,还有什么东西可以完成不将错误转发到下游的任务吗

queryFiles()?.let { files ->
    Observable.fromIterable(files)
            .flatMapSingle { file ->
                uploadFile(file)
                        .onErrorResumeNext { error ->
                            log(error)
                            Single.never() // if this is returned onSuccess is never called
                        }
                        .map { response ->
                            file.id = response.id
                            file
                        }
            }
            .toList()
            .subscribe( { uploadedFiles ->
                persist(uploadedFiles) // if error occurs above, this is never called
            }, { error ->
                log(error)
            })
}

您的问题是,
单个
只能导致两个值,成功或失败。将故障转换为“忽略”状态可以通过首先将其转换为
可能
,然后使用基本相同的代码来处理故障和成功

返回值为
Maybe.empty()
Maybe.onErrorResumeNext
将导致0或1个结果,而
Maybe.map
仅在其具有值时执行,按照您所描述的方法准确处理问题

改编代码:

        .flatMapMaybe { file ->
            uploadFile(file).toMaybe()
                    .onErrorResumeNext { error: Throwable ->
                        log(error)
                        Maybe.empty()
                    }
                    .map { response ->
                        file.id = response.id
                        file
                    }
        }

下面是我过去使用
zip
方法处理它的方式

  // create an observable list that you can process for you file uploads
  val responses: Response = listOf<Response>()

  queryFiles()?.let { file ->

    val observable = Observable.create(ObservableOnSubscribe<Response> { emitter ->
      // you can modify this section to your data types
      try {
        // with your uploadFile method you might be able to just add them
        // all the responses list
        emitter.onNext(uploadFile(file))
        emitter.onComplete()
      } catch (e: Exception) {
        emitter.onError(e)
      }
    }).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread())
    responses.add(observable)    
  }

  // i setup a simple booleanArray to handle success/failure but you can add
  // all the files that fail to a list and use that later    
  val isSuccessful = booleanArrayOf(true)
  Observable.zip<Response, Boolean>(responses, Function<Array<Any>, Boolean> { responses ->
    var isSuccessful: Boolean? = java.lang.Boolean.TRUE
    // handle success or failure
    isSuccessful
  }).subscribe(Consumer<Boolean> { aBoolean -> isSuccessful[0] = aBoolean!! }, Consumer<Throwable> { throwable ->
    isSuccessful[0] = false
  }, Action {
    // handle your OnComplete here
    // I would check the isSuccessful[0] and handle the success or failure        
  })
//创建一个可观察列表,您可以为文件上载处理该列表
val responses:Response=listOf()
queryFiles()?.let{file->
val observable=observable.create(ObservableOnSubscribe{emitter->
//您可以将此部分修改为您的数据类型
试一试{
//使用uploadFile方法,您可以只添加它们
//所有的回答都在列表中
emitter.onNext(上传文件(文件))
emitter.onComplete()
}捕获(e:例外){
发射器。onError(e)
}
}).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread())
回复。添加(可观察)
}
//我设置了一个简单的布尔数组来处理成功/失败,但您可以添加
//所有失败的文件都将列出并在以后使用
val isSuccessful=booleanArrayOf(真)
zip(响应,函数{responses->
var issusccessful:Boolean?=java.lang.Boolean.TRUE
//处理成功或失败
不成功
}).subscribe(消费者{aBoolean->isSuccessful[0]=aBoolean!!},消费者{throwable->
isSuccessful[0]=false
},行动{
//在这里处理你的未完成任务
//我会检查isSuccessful[0]并处理成功或失败
})

这是将所有上传创建到一个可观察对象列表中,可以使用
zip
方法进行处理和合并。当它们被合并到一个数组中时,这将把它们全部合并在一起,这样你就可以在它们上面循环——这是uploadFile()方法的结果。本例检查返回的响应是否成功。我删除了注释
//handle success或failure
所在的大部分逻辑。在函数方法中,您可以跟踪失败或成功的文件上载

谢谢,这很有效。对上述代码所需的唯一更改是明确指定
error:Throwable
的类型,因为方法重载不明确。