简体   繁体   English

等待数据库插入,Kotlin协程

[英]Wait for database insertion, Kotlin Coroutine

I have a class (Repo) that is doing some Room DB and some Retrofit calls.我有一个 class (Repo) 正在执行一些 Room DB 和一些 Retrofit 调用。 For Retrofit calls I am using Rx and for Room I am using Coroutine .对于Retrofit调用,我使用的是Rx ,对于Room ,我使用的是Coroutine

Now the issue is on one button click I have to do perform both DB and API calls.现在问题是单击一个按钮,我必须同时执行 DB 和 API 调用。

  1. Update the some report in DB更新数据库中的一些报告
  2. Upload Images on a server服务器上上传图像
  3. send the report to the server报告发送到服务器
  4. upate report in the DB更新数据库中的报告

Because of the mix of RX and Coroutine, I am unable to make some sequential calls.由于 RX 和 Coroutine 的混合,我无法进行一些顺序调用。 As above mentioned steps MUST BE SEQUENTIAL .如上所述,步骤必须是顺序的。 but the first step takes time to execute and therefore overwrites the data of the last step.但是第一步需要时间来执行,因此会覆盖最后一步的数据。

I want to make sure the first step is done before doing other stuff.我想确保在做其他事情之前完成第一步。

Here is some code I am using这是我正在使用的一些代码

fun submit(
    report : Report,
    images: List<Image>,
    comment: List<Comments>
): Completable {

   var completable: Completable

    runBlocking {
    roomRepo.saveReport(report, images, comment)
   }
      /////////////// Here I need to wait for the above to finish

        val analysisImageList = uploadImages(images)

        completable = myAPi.putAnalysisList(analysisResponse).doOnComplete {
            roomRepo.updateReportStatus(report.id, Pending)
        }.applyNetworkSchedulersCompletable()

    return completable
}

also, this is what saveReport looks like另外,这就是saveReport样子

suspend fun saveReport(
    report : Report,
    images: List<Image>, comment: List<Comments>
) {
    reportDao.insertReportCard(report) /// insertReportCard() is a suspend function

    for (image in images) {
        image.projectId = report.uuid
        imageDao.insertImage(image) /// insertImage() is a suspend function
    }

    comment ?: return
    for (coment in comment) {
        hotspotCommentDao.
insertHotspotComments(coment) /// insertHotspotComments() is a suspend function
    }
}

There might already be a library for this (not sure), but you can create a function for converting Completables to coroutines so you can use them in your coroutine flow.可能已经有一个库(不确定),但您可以创建一个 function 用于将 Completable 转换为协程,以便您可以在协程流程中使用它们。 This function suspends until the blockingAwait() call returns on some background thread.这个 function 会挂起,直到blockingAwait()调用在某个后台线程上返回。

suspend fun Completable.await() = withContext(Dispatchers.Default) {
    blockingAwait()
}

Then your submit function can be a suspend function so you can use it within a coroutine:然后您的submit function 可以是暂停 function 以便您可以在协程中使用它:

suspend fun submit(
    report : Report,
    images: List<Image>,
    comment: List<Comments>
) {
    roomRepo.saveReport(report, images, comment)
    val analysisImageList = uploadImages(images)

    myAPi.putAnalysisList(analysisResponse).doOnComplete {
        roomRepo.updateReportStatus(report.id, Pending)
    }
        .applyNetworkSchedulersCompletable()
        .await()
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM