我正在使用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!!
}
有什么主意吗?
还可以用协程吗?
答案 0 :(得分:1)
我认为您必须将列表(.map
)answerListCreated
到Flowable
的列表中,然后在此列表上使用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()
}
...
}