Преобразование kotlin обратных вызовов в приостановку: возможность вложения? - PullRequest
0 голосов
/ 12 февраля 2020

У меня есть несколько сложных Android обратных вызовов (два последовательных необязательных шага аутентификации с взаимодействием с пользователем), и я пытаюсь преобразовать их в простые функции приостановки.

Итак, я начал с suspendCoroutine и смог заставить первый работать. Ууу!

Но второму нужно позвонить первому. И не похоже, что это «нормальный» способ делать вещи, потому что я не могу вызвать первую функцию приостановки из второй. Даже если я оберну его в «запуск» или «запуск блока», он все равно предупреждает, что я делаю это плохо.

"Неоднозначный coroutineContext из-за приемника CoroutineScope с функцией приостановки" (может быть это? )

Обычно, когда Kotlin это сбивает с толку, это потому, что я делаю плохой выбор архитектуры! Как я могу сделать вложенную приостановку забавной (ctions)?

Pun предназначено.

1 Ответ

0 голосов
/ 12 февраля 2020

Эти функции приостановки, которые вы описываете, звучат так, как будто они выполняют последовательные действия. Им не нужно запускать новые сопрограммы. Ничто не должно быть «вложенным». Это должно выглядеть примерно так (придуманный пример двух разных обратных вызовов, которые возвращают строку):

suspend fun SomeClass.doSomething(msg: String): String =
    suspendCoroutine { cont ->
        doSomething(msg, object: SomeCallback1 {
            override fun onFinished(result: String) {
                cont.resume(msg)
            }
        })
    }

suspend fun SomeClass.doSomethingElse(msg: String): String =
    suspendCoroutine { cont ->
        doSomethingElse(msg, object: SomeCallback2 {
            override fun onFinished(result: String) {
                cont.resume(msg)
            }
        })
    }

suspend fun SomeClass.doBothThingsInSuccession(msg: String): String {
    val firstResult = doSomething(msg)
    return doSomethingElse(firstResult)
}

Если вы пытаетесь скрыть детали, первые две функции приостановки могут быть закрытыми. Или вы можете объединить все в одну функцию:

suspend fun SomeClass.doBothThingsInSuccession(msg: String): String {
    val firstResult: String = suspendCoroutine { cont ->
        doSomething(msg, object: SomeCallback1 {
            override fun onFinished(result: String) {
                cont.resume(result)
            }
        })
    }
    return suspendCoroutine { cont ->
        doSomethingElse(firstResult, object: SomeCallback2 {
            override fun onFinished(result: String) {
                cont.resume(result)
            }
        })
    }
}
...