Un ListenableFuture
représente le résultat d'un calcul asynchrone, c'est-à-dire un calcul qui peut avoir fini de produire un résultat ou non. Il s'agit d'un type de Future
qui vous permet d'enregistrer des rappels à exécuter une fois le calcul terminé, ou immédiatement, s'il est déjà terminé.
ListenableFuture
ne fait pas partie du framework Android et est fourni par Guava. Pour en savoir plus sur l'implémentation de cette classe, consultez la section ListenableFuture en détail.
De nombreuses bibliothèques Jetpack existantes, telles que CameraX ou Services Santé, utilisent des méthodes asynchrones dans lesquelles le type renvoyé est un ListenableFuture
représentant l'état de l'exécution. Dans certains cas, vous devrez peut-être implémenter une méthode qui renvoie un ListenableFuture
, par exemple pour répondre aux exigences de TileService
.
Bibliothèques requises
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") }
Obtenir le résultat d'une ListenableFuture
Ajouter un rappel
Utilisez la méthode d'aide Futures.addCallback(...)
pour associer des rappels de réussite et d'échec à un ListenableFuture
.
Kotlin
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 )
Java
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() );
Suspension en Kotlin
Lorsque vous utilisez Kotlin, le moyen le plus simple d'attendre le résultat d'un ListenableFuture est d'utiliser await()
.
import kotlinx.coroutines.guava.await ... val future: ListenableFuture<QueryResult> = ... val queryResult = future.await() // suspends awaiting success
Interopérabilité avec RxJava
Vous pouvez créer un Single
RxJava à partir d'un ListenableFuture
en enregistrant des rappels dans un SingleEmitter
.
Kotlin
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) }
Java
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));
Créer un ListenableFuture
Créer un avenir immédiat
Si votre API n'est pas asynchrone, mais que vous devez encapsuler le résultat d'une opération terminée dans un ListenableFuture
, vous pouvez créer une ImmediateFuture
. Pour ce faire, utilisez la méthode de fabrique Futures.immediateFuture(...)
.
Kotlin
fun getResult(): ListenableFuture<QueryResult> { try { val queryResult = getQueryResult() return Futures.immediateFuture(queryResult) } catch (e: Exception) { return Futures.immediateFailedFuture(e) } }
Java
public ListenableFuture<QueryResult> getResult() { try { QueryResult queryResult = getQueryResult(); return Futures.immediateFuture(queryResult); } catch (Exception e) { return Futures.immediateFailedFuture(e); } }
Utiliser une coroutine
En langage Kotlin, un future{ ... }
peut être utilisé pour convertir le résultat d'une fonction de suspension en ListenableFuture
.
import kotlinx.coroutines.guava.future suspend fun getResultAsync(): QueryResult { ... } fun getResultFuture(): ListenableFuture<QueryResult> { return coroutineScope.future{ getResultAsync() } }
Convertir un rappel
Pour convertir une API basée sur le rappel en une API qui utilise ListenableFuture
, utilisez CallbackToFutureAdapter
.
Cette API est fournie par l'artefact androidx.concurrent:concurrent-futures
.
Pour en savoir plus, consultez androidx.concurrent.
Conversion depuis RxJava Single
Lorsque vous utilisez RxJava, un Single
peut être converti en SettableFuture
, qui implémente ListenableFuture
.
Kotlin
fun getResult(): ListenableFuture<QueryResult> { val single: Single<QueryResult> = ... val future = SettableFuture.create<QueryResult>() single.subscribe(future::set, future::setException) return future }
Java
public ListenableFuture<QueryResult> getResult() { Single<QueryResult> single = ... SettableFuture<QueryResult> future = SettableFuture.create(); single.subscribe(future::set, future::setException); return future; }