Является ли сбой вызова Continuation.resumeX () обязательно проблемой? - PullRequest
0 голосов
/ 24 марта 2019

Я использую suspendCoroutine, чтобы избежать использования обратных вызовов в Dialog с. Однако в Android Dialog s нет очевидного места для вызова Continuation.resume(), когда диалоговое окно закрыто (щелкнув за пределами области диалога). Если вы попытаетесь позвонить в Dialog.setOnDismissListener(), то вам придется отслеживать, было ли уже вызвано резюме в приемнике кнопки.

suspend fun displayDialog() = suspendCoroutine<String?> { continuation ->
    val builder = AlertDialog.Builder(context)
    builder.setCancelable(true)
    builder.setNegativeButton(android.R.string.cancel) { _, _ ->
        continuation.resume(null)
    }
    builder.setPositiveButton(android.R.string.ok) { _, _ ->
        continuation.resume("it's ok")
    }
    val dialog = builder.show()
    dialog.setOnDismissListener {
        // if the user clicked on OK, then resume has already been called
        // and we get an IllegalStateException
        continuation.resume(null)
    }
}

Итак, лучше отслеживать, было ли уже вызвано резюме (чтобы не вызывать его повторно), или просто не беспокоиться о вызове resume(null) (в onDismissListener)?

1 Ответ

2 голосов
/ 24 марта 2019

Продолжение - это низкоуровневый примитив, который должен быть возобновлен ровно один раз, поэтому вы должны отслеживать, был ли уже вызван resume при его использовании.Кроме того, вы можете использовать коммуникационные примитивы более высокого уровня, например CompletableDeferred, которые имеют многоцелевую функцию complete:

suspend fun displayDialog(): String? {
    val deferred = CompletableDeferred<String?>()
    val builder = AlertDialog.Builder(context)
    builder.setCancelable(true)
    builder.setNegativeButton(android.R.string.cancel) { _, _ ->
        deferred.complete(null)
    }
    builder.setPositiveButton(android.R.string.ok) { _, _ ->
        deferred.complete("it's ok")
    }
    val dialog = builder.show()
    dialog.setOnDismissListener {
        deferred.complete(null)
    }
    return deferred.await()
}
...