ListenableFuture представляет результат асинхронного вычисления: вычисление, которое, возможно, еще не завершило выдачу результата. Это тип Future , который позволяет вам регистрировать обратные вызовы, которые будут выполняться после завершения вычисления или немедленно, если вычисление уже завершено.
ListenableFuture не является частью платформы Android и вместо этого предоставляется Guava . Дополнительные сведения о реализации этого класса см. в разделе «Объяснение ListenableFuture» .
Многие существующие библиотеки Jetpack, такие как CameraX или Health Services, имеют асинхронные методы, тип возвращаемого значения которых — ListenableFuture , который представляет статус выполнения. В некоторых случаях вам может потребоваться реализовать метод, возвращающий ListenableFuture , например, для удовлетворения требований TileService .
Необходимые библиотеки
классный
dependencies { implementation "com.google.guava:guava:31.0.1-android" // To use CallbackToFutureAdapter implementation "androidx.concurrent:concurrent-futures:1.3.0" // Kotlin implementation "org.jetbrains.kotlinx:kotlinx-coroutines-guava:1.6.0" }
Котлин
dependencies { implementation("com.google.guava:guava:31.0.1-android") // To use CallbackToFutureAdapter implementation("androidx.concurrent:concurrent-futures:1.3.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; }