Menggunakan ListenableFuture

ListenableFuture mewakili hasil komputasi asinkron: a komputasi yang mungkin belum selesai memberikan hasil. Ini adalah jenis Future yang memungkinkan Anda mendaftarkan callback untuk dieksekusi setelah komputasi selesai, atau jika komputasi sudah selesai, segera.

ListenableFuture bukan bagian dari framework Android dan diberikan sebagai gantinya oleh Guava. Untuk informasi selengkapnya tentang kelas ini, lihat ListenableFuture dijelaskan.

Banyak library Jetpack yang sudah ada, seperti CameraX atau Fitur Kesehatan memiliki metode asinkron dengan jenis nilai yang ditampilkan adalah ListenableFuture yang mewakili status dalam pelaksanaannya. Dalam beberapa kasus, Anda mungkin perlu mengimplementasikan metode yang mengembalikan ListenableFuture, seperti untuk memenuhi persyaratan TileService.

Library yang diperlukan

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

Mendapatkan hasil ListenableFuture

Menambahkan callback

Menggunakan Futures.addCallback(...) helper untuk memasang callback berhasil dan gagal ke 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()
);

Menangguhkan di Kotlin

Saat menggunakan Kotlin, cara termudah untuk menunggu hasil ListenableFuture adalah menggunakan await().

import kotlinx.coroutines.guava.await

...

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

Interop dengan RxJava

Single RxJava bisa dibuat dari ListenableFuture dengan mendaftarkan callback di dalam 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));

Membuat ListenableFuture

Menciptakan masa depan yang cepat

Jika API Anda tidak asinkron, tetapi Anda perlu menggabungkan hasil menjadi ListenableFuture, Anda dapat membuat ImmediateFuture. Ini dapat dilakukan menggunakan Futures.immediateFuture(...) Factory.

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

Menggunakan coroutine

Di Kotlin, future{ ... } dapat digunakan untuk mengonversi hasil fungsi penangguhan menjadi ListenableFuture.

import kotlinx.coroutines.guava.future

suspend fun getResultAsync(): QueryResult { ... }

fun getResultFuture(): ListenableFuture<QueryResult> {
    return coroutineScope.future{
        getResultAsync()
    }
}

Mengonversi callback

Untuk mengonversi API berbasis callback menjadi API yang menggunakan ListenableFuture, gunakan CallbackToFutureAdapter. API ini disediakan oleh artefak androidx.concurrent:concurrent-futures.

Lihat androidx.concurrent untuk informasi selengkapnya.

Mengonversi dari RxJava Single

Saat menggunakan RxJava, Single dapat dikonversi menjadi SettableFuture, yang mengimplementasikan 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;
}