Korzystanie z elementu ListenableFuture

ListenableFuture reprezentuje wynik obliczeń asynchronicznego: obliczeń, które mogą, ale nie muszą, dać jeszcze wynik. To Future – typ który pozwala rejestrować wywołania zwrotne, które mają być wykonywane po zakończeniu obliczeń a jeśli obliczenia zostały już zakończone, od razu.

ListenableFuture nie jest częścią platformy Androida i została udostępniona. autor: Guava. Więcej informacji na temat implementacji tej klasy znajdziesz w omówieniu funkcji ListenableFuture.

wiele istniejących bibliotek Jetpack, takich jak CameraX; czy usługi zdrowotne korzystają z metod asynchronicznych gdzie zwracanym typem jest ListenableFuture reprezentujący stan i wykonania kodu. W niektórych przypadkach musisz wdrożyć metodę, która zwraca ListenableFuture, tak aby spełnić wymagania TileService.

Wymagane biblioteki

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")
}

Pobieram wynik z ListenableFuture

Dodaję wywołanie zwrotne

Korzystanie z Futures.addCallback(...) metody pomocniczej do dołączania wywołań zwrotnych zakończonych sukcesem i niepowodzeniem 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()
);

Zawieszam w Kotlin

Przy korzystaniu z Kotlin jest to najprostszy sposób oczekiwania na wynik funkcji ListenableFuture to użycie await().

import kotlinx.coroutines.guava.await

...

val future: ListenableFuture<QueryResult> = ...
val queryResult = future.await() // suspends awaiting success

Interakcja z RxJava

RxJava Single można utworzyć z 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

Kreowanie najbliższej przyszłości

Jeśli interfejs API nie jest asynchroniczny, ale trzeba opakować wynik zakończonego w ListenableFuture, możesz utworzyć ImmediateFuture. Ten można to zrobić za pomocą funkcji Futures.immediateFuture(...) fabryczny.

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ółrzędu

W języku Kotlin future{ ... } może posł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()
    }
}

Konwertowanie wywołania zwrotnego

Aby przekonwertować interfejs API oparty na wywołaniach zwrotnych na taki, który używa interfejsu ListenableFuture, użyj funkcji CallbackToFutureAdapter Ten interfejs API jest dostarczany przez artefakt androidx.concurrent:concurrent-futures.

Więcej informacji znajdziesz na stronie androidx.concurrent.

Konwertuję z RxJava Single

Jeśli używasz RxJava, Single można przekonwertować na SettableFuture, która implementuje funkcję 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;
}