简体   繁体   中英

Wait for database insertion, Kotlin Coroutine

I have a class (Repo) that is doing some Room DB and some Retrofit calls. For Retrofit calls I am using Rx and for Room I am using Coroutine .

Now the issue is on one button click I have to do perform both DB and API calls.

  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. 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

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. This function suspends until the blockingAwait() call returns on some background thread.

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:

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()
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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