Блокировка при использовании сопрограммы runBlocking для получения результата Firebase AuthUI.signOut () - PullRequest
0 голосов
/ 02 ноября 2018

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

Итак, мое игрушечное приложение основано на архитектуре MVVM и использует Firebase для реализации функций входа / выхода. И есть вариант использования SignOut:

class FirebaseSignOut @Inject constructor(private val firebaseAuthUi: AuthUI) : SignOut {
    private lateinit var signOutResult: SignOutResult

    override fun execute(context: Context): SignOutResult {
        runBlocking {
            signOutResult = getSignOutResult(context)
        }

        return signOutResult
    }

    private suspend fun getSignOutResult(context: Context): SignOutResult {
        return suspendCoroutine { continuation ->
            firebaseAuthUi.signOut(context)
                    .addOnSuccessListener {
                        continuation.resume(SignOutSuccess)
                    }
                    .addOnFailureListener {
                        continuation.resume(SignOutError)
                    }
                    .addOnCanceledListener {
                        continuation.resume(SignOutCancel)
                    }
        }
    }

}

Проблема

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

Я выяснил, что сама логика сопрограмм не является проблемой, заменив getSignOutResult () на mock, например:

private suspend fun getSignOutResult(context: Context): SignOutResult {
    delay(500)
    return SignOutError
}

Тогда я смог отследить блокировку до этой части AuthUI Firebase:

return Tasks.whenAll(
        signOutIdps(context),
        maybeDisableAutoSignIn
).continueWith(new Continuation<Void, Void>() {

https://github.com/firebase/FirebaseUI-Android/blob/master/auth/src/main/java/com/firebase/ui/auth/AuthUI.java#L325

private Task<Void> signOutIdps(@NonNull Context context) {
    ...
    return GoogleSignIn.getClient(context, GoogleSignInOptions.DEFAULT_SIGN_IN).signOut();
}

https://github.com/firebase/FirebaseUI-Android/blob/master/auth/src/main/java/com/firebase/ui/auth/AuthUI.java#L403

и выясните, что может быть DisableAutoSignIn Task никогда не запускается. Итак, тупик, возникающий где-то внутри signOut () GoogleSignIn, который не может отследить.

Вопрос

У кого-нибудь есть идея, почему такой тупик может случиться? И любое предложение, как решить проблему, очень приветствуется.

Подробности конфигурации

Я использую последние версии библиотек Kotlin и Firebase

firebaseCoreVersion = '16.0.4'
firebaseUiVersion = '4.1.0'
kotlinVersion = '1.3.0'
kotlinCoroutinesVersion = '1.0.0'

AuthUI разрешил использовать только вход в Google.


! ПОЖАЛУЙСТА, ОБРАТИТЕ ВНИМАНИЕ , что я знаю, что я могу сделать переменную signOutResult наблюдаемой. Но в этом случае execute не сможет вернуть результат. И я действительно хочу это сделать, потому что такая реализация легко поддается проверке. И тот факт, что runBlocking блокирует основной поток для выхода, является приемлемым в моем случае - имеет смысл, что пользовательский интерфейс недоступен во время процедуры, поскольку пользовательский интерфейс значительно изменяется в зависимости от состояния аутентификации.

...