Un ListenableFuture rappresenta il risultato di un calcolo asincrono:
di calcolo che potrebbe aver già terminato o meno di produrre un risultato. È una
tipo di Future
che consente di registrare i callback da eseguire dopo che il calcolo
o, se il calcolo è già stato completato, immediatamente.
ListenableFuture non fa parte del framework Android e viene invece fornito
di Guava. Per ulteriori informazioni
di questa classe, consulta la spiegazione di ListenableFuture.
Molte librerie Jetpack esistenti, ad esempio CameraX
o i servizi sanitari hanno metodi asincroni
dove il tipo restituito è ListenableFuture che rappresenta lo stato di
l'esecuzione. In alcuni casi, potrebbe essere necessario implementare un metodo che restituisca un
ListenableFuture, in modo da soddisfare i requisiti di TileService.
Librerie obbligatorie
Alla moda
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" }
Kotlin
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") }
Recupero del risultato di un ListenableFuture
Aggiunta di un callback
Utilizza la Futures.addCallback(...)
helper per collegare i callback di esito positivo e negativo 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 usi Kotlin, il modo più semplice per attendere il risultato di un ListenableFuture
consiste nell'utilizzare await().
import kotlinx.coroutines.guava.await ... val future: ListenableFuture<QueryResult> = ... val queryResult = future.await() // suspends awaiting success
Interoperabilità con RxJava
Un file RxJava Single
può essere creato da un ListenableFuture registrando i callback all'interno di 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));
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 in un ListenableFuture, puoi creare un ImmediateFuture. Questo
può essere eseguita utilizzando 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); } }
Uso di una coroutina
In Kotlin, una future{ ... }
può essere utilizzato 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, vedi androidx.concurrent.
Conversione da RxJava Single in corso...
Quando utilizzi RxJava, viene utilizzato un parametro Single
può essere convertito in un elemento 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; }