ListenableFuture
представляет результат асинхронного вычисления: вычисление, которое, возможно, еще не завершило выдачу результата. Это тип Future
, который позволяет вам регистрировать обратные вызовы, которые будут выполняться после завершения вычисления или немедленно, если вычисление уже завершено.
ListenableFuture
не является частью платформы Android и вместо этого предоставляется Guava . Дополнительные сведения о реализации этого класса см. в разделе «Объяснение ListenableFuture» .
Многие существующие библиотеки Jetpack, такие как CameraX или Health Services, имеют асинхронные методы, тип возвращаемого значения которых — ListenableFuture
, который представляет статус выполнения. В некоторых случаях вам может потребоваться реализовать метод, возвращающий ListenableFuture
, например, для удовлетворения требований TileService
.
Необходимые библиотеки
Groovy
dependencies { implementation "com.google.guava:guava:31.0.1-android" // To use CallbackToFutureAdapter implementation "androidx.concurrent:concurrent-futures:1.2.0" // Kotlin implementation "org.jetbrains.kotlinx:kotlinx-coroutines-guava:1.6.0" }
Kotlin
dependencies { implementation("com.google.guava:guava:31.0.1-android") // To use CallbackToFutureAdapter implementation("androidx.concurrent:concurrent-futures:1.2.0") // Kotlin implementation("org.jetbrains.kotlinx:kotlinx-coroutines-guava:1.6.0") }
Получение результата ListenableFuture
Добавление обратного вызова
Используйте вспомогательный метод Futures.addCallback(...)
для прикрепления обратных вызовов успешного и неудачного выполнения к ListenableFuture
.
Котлин
val future: ListenableFuture<QueryResult> = ... Futures.addCallback( future, object : FutureCallback<QueryResult> { override fun onSuccess(result: QueryResult) { // handle success } override fun onFailure(t: Throwable) { // handle failure } }, // causes the callbacks to be executed on the main (UI) thread context.mainExecutor )
Ява
ListenableFuture<QueryResult> future = ... Futures.addCallback( future, new FutureCallback<QueryResult>() { public void onSuccess(QueryResult result) { // handle success } public void onFailure(@NonNull Throwable thrown) { // handle failure } }, // causes the callbacks to be executed on the main (UI) thread context.getMainExecutor() );
Приостановка в Котлине
При использовании Kotlin самый простой способ дождаться результата ListenableFuture — использовать await()
.
import kotlinx.coroutines.guava.await ... val future: ListenableFuture<QueryResult> = ... val queryResult = future.await() // suspends awaiting success
Взаимодействие с RxJava
RxJava Single
можно создать из ListenableFuture
путем регистрации обратных вызовов внутри SingleEmitter
.
Котлин
val future: ListenableFuture<QueryResult> = ... val single = Single.create<QueryResult> { Futures.addCallback(future, object : FutureCallback<QueryResult> { override fun onSuccess(result: QueryResult) { it.onSuccess(result) } override fun onFailure(t: Throwable) { it.onError(t) } }, executor) }
Ява
ListenableFuture<QueryResult> future = ... Single<QueryResult> single = Single.create( e -> Futures.addCallback(future, new FutureCallback<QueryResult>() { @Override public void onSuccess(QueryResult result) { e.onSuccess(result); } @Override public void onFailure(@NonNull Throwable thrown) { e.onError(thrown); } }, executor));
Создание ListenableFuture
Создание ближайшего будущего
Если ваш API не асинхронный, но вам нужно обернуть результат завершенной операции в ListenableFuture
, вы можете создать ImmediateFuture
. Это можно сделать с помощью фабричного метода Futures.immediateFuture(...)
.
Котлин
fun getResult(): ListenableFuture<QueryResult> { try { val queryResult = getQueryResult() return Futures.immediateFuture(queryResult) } catch (e: Exception) { return Futures.immediateFailedFuture(e) } }
Ява
public ListenableFuture<QueryResult> getResult() { try { QueryResult queryResult = getQueryResult(); return Futures.immediateFuture(queryResult); } catch (Exception e) { return Futures.immediateFailedFuture(e); } }
Использование сопрограммы
В Kotlin future{ ... }
можно использовать для преобразования результата функции приостановки в ListenableFuture
.
import kotlinx.coroutines.guava.future suspend fun getResultAsync(): QueryResult { ... } fun getResultFuture(): ListenableFuture<QueryResult> { return coroutineScope.future{ getResultAsync() } }
Преобразование обратного вызова
Чтобы преобразовать API на основе обратного вызова в API, использующий ListenableFuture
, используйте CallbackToFutureAdapter
. Этот API предоставляется артефактом androidx.concurrent:concurrent-futures
.
Дополнительную информацию см. в androidx.concurrent .
Преобразование из RxJava Single
При использовании RxJava Single
можно преобразовать в SettableFuture
, который реализует ListenableFuture
.
Котлин
fun getResult(): ListenableFuture<QueryResult> { val single: Single<QueryResult> = ... val future = SettableFuture.create<QueryResult>() single.subscribe(future::set, future::setException) return future }
Ява
public ListenableFuture<QueryResult> getResult() { Single<QueryResult> single = ... SettableFuture<QueryResult> future = SettableFuture.create(); single.subscribe(future::set, future::setException); return future; }