Pole ListenableFuture
jest wynikiem obliczeń asynchronicznych, czyli obliczeń, które mogły, ale nie muszą, nie zostały jeszcze zakończone. Jest to typ Future
, który umożliwia rejestrowanie wywołań zwrotnych, które są wykonywane po zakończeniu obliczeń lub od razu, gdy przetwarzanie już się zakończyło.
ListenableFuture
nie jest częścią platformy Androida. Zamiast niego jest dostarczany przez Guava. Więcej informacji o implementacji tej klasy znajdziesz w tym artykule.
Wiele istniejących bibliotek Jetpack, takich jak CameraX i Health Services, ma metody asynchroniczne, w których zwracany typ to ListenableFuture
, który reprezentuje stan wykonania. W niektórych przypadkach może być konieczne wdrożenie metody, która zwraca wartość ListenableFuture
, np. aby spełnić wymagania TileService
.
Wymagane biblioteki
Odlotowy
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") }
Pobieram wynik: ListenableFuture
Dodawanie wywołania zwrotnego
Użyj Futures.addCallback(...)
metody pomocniczej, aby dołączyć udane i nieudane wywołania zwrotne do 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() );
Zawieszenie w Kotlin
W przypadku korzystania z Kotlin najprostszym sposobem oczekiwania na wynik elementu ListenableFuture jest użycie właściwości await()
.
import kotlinx.coroutines.guava.await ... val future: ListenableFuture<QueryResult> = ... val queryResult = future.await() // suspends awaiting success
Interakcja z RxJava
Obiekt RxJava Single
można utworzyć na podstawie ListenableFuture
, rejestrując wywołania zwrotne w 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));
Tworzę ListenableFuture
Tworzenie najbliższej przyszłości
Jeśli interfejs API nie jest asynchroniczny, ale chcesz umieścić wynik zakończonej operacji w elemencie ListenableFuture
, możesz utworzyć obiekt ImmediateFuture
. Można to zrobić za pomocą metody fabrycznej 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); } }
Korzystanie z współprogramowania
W Kotlin obiekt future{ ... }
może służyć do konwertowania wyniku funkcji zawieszania na ListenableFuture
.
import kotlinx.coroutines.guava.future suspend fun getResultAsync(): QueryResult { ... } fun getResultFuture(): ListenableFuture<QueryResult> { return coroutineScope.future{ getResultAsync() } }
Konwersja wywołania zwrotnego
Aby przekonwertować interfejs API oparty na wywołaniach zwrotnych na taki, który korzysta z ListenableFuture
, użyj CallbackToFutureAdapter
.
Ten interfejs API jest dostarczany przez artefakt androidx.concurrent:concurrent-futures
.
Więcej informacji znajdziesz na stronie androidx.concurrent.
Konwersja z formatu RxJava Single
Korzystając z RxJava, Single
można przekonwertować na plik SettableFuture
z implementacją 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; }