如何等到一堆电话结束再打一个电话

How to wait until a bunch of calls ends to make another call

我正在使用 RxJava 并且我知道 concat,我想它确实适合我,因为我想先完成所有第一个电话然后再进行第二个电话但是不知道怎么实现。

我现在有这个:

private fun assignAllAnswersToQuestion(questionId: Long) {

        answerListCreated.forEach { assignAnswerToQuestion(questionId, it.id) }

    }

    private fun assignAnswerToQuestion(questionId: Long, answerId: Long) {
        disposable = questionService.addAnswerToQuestion(questionId,answerId,MyUtils.getAccessTokenFromLocalStorage(context = this))
        .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(
                {
                    result -> //Do nothing it should call the next one

                },
                { error -> toast(error.message.toString())}
            )
    }

但是,一旦完成所有这些 forEach 我想做这样的事情:

private fun assignAllAnswersToQuestion(questionId: Long) {

   answerListCreated.forEach { assignAnswerToQuestion(questionId, it.id) 
   anotherCallHere(questionId) //Do it when the first forEach is finished!!

}

有什么想法吗?

此外,是否有一种方法可以使用协程来实现?

我认为你必须 .map 你的列表 (answerListCreated) 到 Flowable 的列表,然后在这个列表上使用 Flowable.zip
zip 用于将 Flowable 的结果合并为一个结果。由于您不需要这些结果,我们将忽略它们。
zip 之后你确定之前的所有 Flowable 都结束了,你可以 .flatMap 执行你的下一个调用(假设 anotherCallHere returns a Flowable.

最后会是这样的:

val flowableList = answerListCreated.map { assignAnswerToQuestion(questionId, it.id) }

disposable = Flowable.zip(flowableList) { /* Ignoring results */ }
    .flatMap { anotherCallHere(questionId) }
    .subscribeOn(Schedulers.io())
    .observeOn(AndroidSchedulers.mainThread())
    .subscribe {
        // ...
    }

需要注意的是,如果任何一个调用失败,整个链都会失败(onError将被调用)。

我是协程的新手,但我想我可以为他们解答:

您可以为此使用协程 runBlocking {}。

private fun assignAllAnswersToQuestion(questionId: Long) = launch {
    runBlocking {
        answerListCreated.forEach { assignAnswerToQuestion(questionId, it.id) }
    }
    anotherCallHere(questionId)
}

private fun assignAnswerToQuestion(questionId: Long, answerId: Long) = launch (Dispatchers.IO) {
    questionService.addAnswerToQuestion(
        questionId,
        answerId,
        MyUtils.getAccessTokenFromLocalStorage(context = this)
    )
}

启动 {} returns 成为父协程的子作业的作业对象。 runBlocking {} 将阻塞,直到它的所有子作业都完成,(另一种方法是使用 launch {}.join() ,它会产生相同的影响)。

请注意,我已将这两个函数的代码包装在启动 {} 块中。 为了能够像这样调用 launch {},您可能希望 class 实现 CoroutineScope

class MyActivityOrFragment: Activity(), CoroutineScope {
    lateinit var job = SupervisorJob()
    private val exceptionHandler =
        CoroutineExceptionHandler { _, error ->
            toast(error.message.toString()
        }
    override val coroutineContext = Dispatchers.Main + job + exceptionHandler

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        job = Job()
    }

    override fun onDestroy() {
        super.onDestroy()
        job.cancel()
    }

    ...
}