Estoy usando suspendCoroutine para evitar el uso de devoluciones de llamada en Dialog s. Sin embargo, en Android Dialog s no hay un lugar obvio para llamar a Continuation.resume() cuando se descarta el diálogo (haciendo clic fuera del área de diálogo). Si intenta la llamada en Dialog.setOnDismissListener() , entonces debe realizar un seguimiento de si ya se llamó a resume en el botón de escucha.
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) } } Entonces, ¿es mejor hacer un seguimiento de si ya se llamó a resume (para evitar llamarlo por segunda vez), o simplemente no molestarse con la llamada resume(null) (en onDismissListener)?
La continuación es una primitiva de bajo nivel que se reanudará exactamente una vez, por lo que debe realizar un seguimiento de si ya se llamó a resume al usarlo. Alternativamente, puede usar primitivas de comunicación de nivel superior, por ejemplo CompletableDeferred , que tiene una función complete de usos múltiples:
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() }