ожидание моего кода до sh получения всей информации от вызова API с использованием Kotlin - PullRequest
1 голос
/ 21 января 2020

Привет, я новичок в Kotlin

Я пытаюсь написать следующий код -

private fun syncLocalCartItemsToNetwork(tokenObject: MyVerteUserAuthTokenObject) {
        val failedSyncedProducts: MutableList<String> = mutableListOf()


        locallySavedCartModels.forEach { //I need to make the code wait until all callbacks from this loop finishes
            ShoppingCartUtils.addItemToCart(tokenObject.token, it, this@ShoppingCartActivity, object : ShoppingCartUtils.OnMyVerteCartProductsSyncListener {
                override fun onProductSyncFailed(productID: String) {
                    failedSyncedProducts.add(productID)
                }
            })
        }

        if (failedSyncedProducts.isNotEmpty()) {
            val builder = AlertDialog.Builder(this)
            builder.setTitle("Shopping Cart was not fully synced")
            builder.setMessage("The following items were not synced well due to stock availability, please re add them - \n\n" +
                    "${failedSyncedProducts.forEach { it + "\n\n" }}")
            builder.setPositiveButton("Confirm") { dialog, _ ->
                dialog.dismiss()
            }
            val dialog: AlertDialog = builder.create()
            dialog.show()
        }
        Toast.makeText(this@ShoppingCartActivity, "finished", Toast.LENGTH_SHORT).show()


    }

Как видите, я перебираю все locallySavedCartModels и возможно получить из него результат.

Мне нужна опция, чтобы заставить функцию ждать, пока все обратные вызовы не завершатся sh из forEach l oop, только затем продолжить мой код, чтобы проверить, является ли моя строка список пуст или нет.

Как я могу сделать это, используя Kotlin?

1 Ответ

1 голос
/ 21 января 2020

Скорее всего, будет лучше использовать сопрограммы, но это будет означать переписывание ваших ShoppingCartUtils для использования функций приостановки вместо обратных вызовов.

Чтобы работать с тем, что у вас есть, одним из способов может быть создание класса, который выполняет оставшийся код, когда он вызывается достаточно раз, например:

class CallbackAggregator(val count: Int) {
    var finalCallback: (() -> Unit)? = null
    private var calls = 0

    fun increment() {
        if (++calls == count)
            finalCallback?.invoke()
    }
}

Использование:

private fun syncLocalCartItemsToNetwork(tokenObject: MyVerteUserAuthTokenObject) {
    val failedSyncedProducts: MutableList<String> = mutableListOf()

    val aggregator = CallbackAggregator(locallySavedCartModels.size)

    locallySavedCartModels.forEach { 
        ShoppingCartUtils.addItemToCart(tokenObject.token, it, this@ShoppingCartActivity, object : ShoppingCartUtils.OnMyVerteCartProductsSyncListener {
                override fun onProductSyncFailed(productID: String) {
                    failedSyncedProducts.add(productID)
                    aggregator.increment()
                }
            })
        }

    aggregator.finalCallback = {
        if (failedSyncedProducts.isNotEmpty()) {
            AlertDialog.Builder(this@ShoppingCartActivity).apply {
                title = "Shopping Cart was not fully synced"
                message = "The following items were not synced well due to stock availability, please re add them - \n\n" +
                    "${failedSyncedProducts.joinToString("\n\n")}")
                setPositiveButton("Confirm") { dialog, _ ->
                    dialog.dismiss()
                }
                create().show()
            }
        }
        Toast.makeText(this@ShoppingCartActivity, "finished", Toast.LENGTH_SHORT).show()
    }
}
...