Un ListenableFuture
rappresenta il risultato di un calcolo asincrono: un calcolo che potrebbe aver terminato o meno di produrre un risultato. È un tipo di Future
che consente di registrare i callback da eseguire subito dopo il completamento del calcolo o, se il calcolo è già stato completato.
ListenableFuture
non fa parte del framework Android ed è fornito da Guava. Per ulteriori informazioni sull'implementazione di questo corso, consulta la spiegazione diListenableFuture.
Molte librerie Jetpack esistenti, come FotocameraX o Health Services, dispongono di metodi asincroni in cui il tipo restituito è ListenableFuture
, che rappresenta lo stato dell'esecuzione. In alcuni casi, potrebbe essere necessario implementare un metodo che restituisca un elemento
ListenableFuture
, ad esempio per soddisfare i requisiti di TileService
.
Librerie richieste
Trendy
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") }
Recupero del risultato di ListenableFuture
in corso...
Aggiunta di un callback
Utilizza il metodo helper Futures.addCallback(...)
per collegare i callback di operazione riuscita e non riuscita a 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() );
Sospensione in Kotlin
Quando utilizzi Kotlin, il modo più semplice di attendere il risultato di AscoltaableFuture
è utilizzare await()
.
import kotlinx.coroutines.guava.await ... val future: ListenableFuture<QueryResult> = ... val queryResult = future.await() // suspends awaiting success
Interopera con RxJava
È possibile creare un codice RxJava Single
da un elemento ListenableFuture
registrando i callback all'interno di un elemento 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));
Creazione di un ListenableFuture
in corso...
Creare un futuro immediato
Se l'API non è asincrona, ma devi eseguire il wrapping del risultato di un'operazione completata in un ListenableFuture
, puoi creare un elemento ImmediateFuture
. Questa operazione
può essere eseguita utilizzando il metodo di fabbrica 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); } }
Utilizzo di una coroutine
In Kotlin, è possibile utilizzare un elemento future{ ... }
per convertire il risultato di una funzione di sospensione in un ListenableFuture
.
import kotlinx.coroutines.guava.future suspend fun getResultAsync(): QueryResult { ... } fun getResultFuture(): ListenableFuture<QueryResult> { return coroutineScope.future{ getResultAsync() } }
Conversione di un callback
Per convertire un'API basata su callback in un'API che utilizza ListenableFuture
, utilizza
CallbackToFutureAdapter
.
Questa API è fornita dall'artefatto androidx.concurrent:concurrent-futures
.
Per ulteriori informazioni, visita la pagina androidx.concurrent.
Conversione da RxJava Single
in corso...
Quando utilizzi RxJava, una Single
può essere convertita in un SettableFuture
, che implementa 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; }