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

时间:2019-03-14 19:53:45

标签: android kotlin rx-java

我正在使用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!!

}

有什么主意吗?

还可以用协程吗?

2 个答案:

答案 0 :(得分:1)

我认为您必须将列表(.mapanswerListCreatedFlowable的列表中,然后在此列表上使用Flowable.zip
zip用于将Flowable的结果合并为一个结果。由于您不需要这些结果,因此我们将其忽略。
zip之后,您确定之前所有Flowable都结束了,并且可以.flatMap执行下一个调用(假设anotherCallHere返回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)。

答案 1 :(得分:0)

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

您可以为此使用协程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)
    )
}

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

请注意,我已经使两个函数都将它们的代码包装在launch {}块中。 为了能够像这样调用启动{},您可能希望使您的类实现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()
    }

    ...
}