Um ListenableFuture
representa o resultado de um cálculo assíncrono: um
computação que pode ou não ter concluído a produção de um resultado. É um
tipo de Future
que permite registrar callbacks a serem executados quando o cálculo for
concluído, ou se o cálculo já estiver concluído, imediatamente.
ListenableFuture
não faz parte do framework do Android e é fornecido
por Guava. Para mais informações sobre o
implementação dessa classe, consulte a explicação do ListenableFuture.
Muitas bibliotecas do Jetpack, como CameraX
ou Recursos de saúde têm métodos assíncronos
em que o tipo de retorno é ListenableFuture
, que representa o status da
a execução. Em alguns casos, pode ser necessário implementar um método que retorne uma
ListenableFuture
, para atender aos requisitos de TileService
.
Bibliotecas necessárias
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") }
Como receber o resultado de um ListenableFuture
Como adicionar uma chamada de retorno
Usar o Futures.addCallback(...)
método auxiliar para anexar callbacks de sucesso e falha a um 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() );
Suspensão no Kotlin
Ao usar o Kotlin, a maneira mais fácil de esperar pelo resultado de um ListenableFuture
é usar await()
.
import kotlinx.coroutines.guava.await ... val future: ListenableFuture<QueryResult> = ... val queryResult = future.await() // suspends awaiting success
Interoperabilidade com RxJava
Um Single
RxJava
podem ser criadas a partir de ListenableFuture
, registrando callbacks dentro de
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));
Como criar um ListenableFuture
Criação de um futuro imediato
Se a API não for assíncrona, mas você precisar unir o resultado de um
operação em um ListenableFuture
, é possível criar um ImmediateFuture
. Isso
pode ser feito usando o Futures.immediateFuture(...)
de fábrica.
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); } }
Como usar uma corrotina
Em Kotlin, um future{ ... }
(link em inglês)
pode ser usada para converter o resultado de uma função de suspensão em um ListenableFuture
.
import kotlinx.coroutines.guava.future suspend fun getResultAsync(): QueryResult { ... } fun getResultFuture(): ListenableFuture<QueryResult> { return coroutineScope.future{ getResultAsync() } }
Como converter um callback
Para converter uma API baseada em callback em uma que usa ListenableFuture
, use
CallbackToFutureAdapter
.
Essa API é fornecida pelo artefato androidx.concurrent:concurrent-futures
.
Consulte androidx.concurrent para mais informações.
Como converter do Single
do RxJava
Ao usar RxJava, um Single
podem ser convertidos em um SettableFuture
,
que 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; }