Что возвращается внутри onComplete
Комментарии (4)
Ответ сгенерирован нейросетью и может содержать ошибки
Отличный вопрос, который касается одной из ключевых концепций современных асинхронных API в Android, особенно в Kotlin Coroutines и Google Play Services (Tasks).
Ответ зависит от контекста: о каком конкретно onComplete идет речь. Рассмотрим два основных случая.
1. OnComplete в Kotlin Coroutines (в Flow)
В Kotlin корутинах onComplete как отдельного колбэка нет. Есть оператор onCompletion, который является частью Flow API. Это не возвращаемое значение, а terminal operator или intermediate operator, который позволяет выполнить действие при завершении потока данных (Flow), независимо от того, было оно нормальным или с ошибкой.
Что "возвращается" внутри лямбды onCompletion?
В его лямбду передается параметр типа Throwable? (cause).
- Если
cause == null— поток завершился успешно. - Если
cause != null— поток завершился с ошибкой.
Сам оператор onCompletion возвращает новый Flow, который эмитит те же значения, что и исходный, но выполняет переданное действие по завершении.
fun fetchDataFlow(): Flow<String> = flow {
emit("Data Chunk 1")
emit("Data Chunk 2")
// throw RuntimeException("Network error") // Раскомментировать для ошибки
}
// Использование
viewModelScope.launch {
fetchDataFlow()
.onEach { value -> Log.d("Flow", "Received: $value") }
.onCompletion { cause ->
// Анализируем параметр cause
if (cause == null) {
Log.d("Flow", "Flow completed SUCCESSFULLY")
} else {
Log.e("Flow", "Flow completed with ERROR: ${cause.message}")
}
}
.collect() // Запускаем поток
}
Ключевой момент: onCompletion не перехватывает ошибку. Чтобы обработать ошибку и продолжить работу, нужно использовать оператор catch.
2. OnComplete в Google Play Services (Task API)
Это классический колбэк-паттерн, используемый в API Firebase, Google Sign-In, Location Services и др. Task<T> представляет асинхронную операцию с результатом типа T.
Метод addOnCompleteListener регистрирует слушатель, который вызывается, когда задача (Task) завершена — независимо от успеха или провала.
Что "возвращается" внутри лямбды onComplete?
В лямбду передается сам объект Task<T>. Чтобы получить результат или ошибку, нужно проанализировать эту задачу внутри колбэка.
// Пример с Firebase Auth
auth.signInWithEmailAndPassword(email, password)
.addOnCompleteListener { task: Task<AuthResult> -> // task - это параметр
// 1. Проверяем, успешна ли задача
if (task.isSuccessful) {
// 2. Если да, БЕЗОПАСНО извлекаем результат.
// task.result может выбросить исключение, если задача не успешна!
val result: AuthResult? = task.result
val user = result?.user
Log.d("Auth", "Success: ${user?.email}")
} else {
// 3. Если задача не успешна, получаем исключение.
// task.exception гарантированно не-null при isSuccessful == false
val exception = task.exception
Log.e("Auth", "Sign-in failed", exception)
}
}
Критически важные методы объекта Task, доступные внутри onComplete:
isSuccessful:Boolean— флаг успешного завершения.result:T?— возвращает результат только если задача успешна. Вызов этого метода у неуспешной задачи выброситRuntimeExecutionException!exception:Exception?— возвращает исключение, если задача не успешна. Для успешной задачи возвращаетnull.
Сравнительная таблица
| Критерий | onCompletion (Kotlin Flow) | onComplete (Play Services Task) |
|---|---|---|
| Контекст | Асинхронный поток данных (Flow) | Единая асинхронная задача (Task) |
| Параметр в лямбде | Throwable? cause | Объект Task<T> |
| Как узнать об успехе | cause == null | task.isSuccessful |
| Как получить результат | Не предназначен для этого. Результаты — в collect или onEach. | task.result (только если isSuccessful == true) |
| Как получить ошибку | Параметр cause (если не null) | task.exception (если isSuccessful == false) |
| Возвращаемое значение метода | Новый Flow | this (сам Task для чейнинга) |
| Стиль | Декларативный, реактивный | Императивный, колбэк-ориентированный |
Вывод: Внутри onCompletion для Flow вы получаете исключение-причину завершения (Throwable?), а внутри onComplete для Task — вы получаете саму задачу (Task<T>), которую вы должны вручную проверить на успех (isSuccessful) и безопасно извлечь из неё результат или исключение. Это отражает эволюцию от колбэк-адского подхода к более безопасному и декларативному стилю корутин.