如何等到一堆电话结束再打一个电话
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()
}
...
}
我正在使用 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()
}
...
}