【问题标题】:How to wait until a bunch of calls ends to make another call如何等到一堆电话结束再拨打另一个电话
【发布时间】:2019-03-14 19:53:44
【问题描述】:

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

}

有什么想法吗?

另外,这是一种使用协程的方法吗?

【问题讨论】:

    标签: android kotlin rx-java


    【解决方案1】:

    我认为你必须将.map你的列表(answerListCreated)添加到Flowables的列表中,然后在这个列表中使用Flowable.zip
    zip是用来合并结果的Flowables 变成一个结果。由于您不需要这些结果,我们将忽略它们。
    zip 之后,您确定之前的所有Flowables 都结束了,您可以.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,2,3,4,5 然后抓取 3 例如,所以我想先完成添加到列表然后制作调用grabX
    • 当您使用zip 时,您会传递Flowables 和lambda 的列表。在 lambda 中,您可以访问您传入的 Flowables 的结果。像这样:Flowable.zip(flowableList) { resultList -> /* Use list of results */ }
    • 因此,如果您看一下我的问题,我已经编辑了一些阅读“但是”的内容,我该如何实现此代码?你能编辑你的答案吗?
    • 对不起,我不明白你在问什么。我当前的答案解决了这个问题:1)执行 all assignAnswerToQuestion 调用 2)然后执行 anotherCallHere
    【解决方案2】:

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

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

    launch {} 返回一个 Job 对象,该对象成为父协程的子作业。 runBlocking {} 将阻塞,直到其所有子作业完成为止,(另一种方法是使用具有相同效果的启动 {}.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()
        }
    
        ...
    }
    
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-12-21
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多