การใช้อนาคตที่ฟังได้

ListenableFuture แสดงถึงผลลัพธ์ของการคำนวณแบบไม่พร้อมกัน: ที่สามารถคำนวณผลลัพธ์หรือไม่ก็ได้ เป็น ประเภทของ Future ซึ่งให้คุณลงทะเบียน Callback ที่จะทำงานเมื่อมีการคำนวณ เสร็จสมบูรณ์ หรือหากการคำนวณนั้นเสร็จสมบูรณ์ ในทันที

ListenableFuture ไม่ได้เป็นส่วนหนึ่งของเฟรมเวิร์ก Android แต่จัดหาให้แทน โดย Guava ดูข้อมูลเพิ่มเติมเกี่ยวกับ การนำคลาสนี้ไปใช้ โปรดดูคำอธิบาย ListenableFuture

มีไลบรารี Jetpack ที่มีอยู่จำนวนมาก เช่น cameraX หรือบริการข้อมูลสุขภาพมีวิธีการที่ไม่พร้อมกัน โดยที่ประเภทการแสดงผลเป็น ListenableFuture ซึ่งแสดงถึงสถานะของ การลงมือปฏิบัติ ในบางกรณี คุณอาจต้องใช้เมธอดที่ส่งคืน ListenableFuture เช่น เพื่อให้เป็นไปตามข้อกำหนด TileService

ไลบรารีที่จำเป็น

ดึงดูด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"
}
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")
}

การรับผลลัพธ์ของ ListenableFuture

การเพิ่ม Callback

ใช้Futures.addCallback(...) เมธอด Helper ในการแนบ Callback ที่สำเร็จและล้มเหลวไปยัง ListenableFuture

KotlinJava
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
)
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()
);

การระงับใน Kotlin

เมื่อใช้ Kotlin วิธีที่ง่ายที่สุดในการรอผลลัพธ์ของ ListenableFuture คือการใช้ await()

import kotlinx.coroutines.guava.await

...

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

การทำงานร่วมกับ RxJava

RxJava Single สามารถสร้างจาก ListenableFuture โดยการลงทะเบียน Callback ภายใน SingleEmitter

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

กำลังสร้าง ListenableFuture

สร้างอนาคตที่ใกล้เข้ามา

หาก API ของคุณไม่ใช่แบบอะซิงโครนัส แต่คุณต้องรวมผลลัพธ์ของ ใน ListenableFuture คุณก็สามารถสร้าง ImmediateFuture ได้ ช่วงเวลานี้ คุณสามารถทำได้โดยใช้Futures.immediateFuture(...) จากโรงงาน

KotlinJava
fun getResult(): ListenableFuture<QueryResult> {
    try {
        val queryResult = getQueryResult()
        return Futures.immediateFuture(queryResult)
    } catch (e: Exception) {
        return Futures.immediateFailedFuture(e)
    }
}
public ListenableFuture<QueryResult> getResult() {
    try {
        QueryResult queryResult = getQueryResult();
        return Futures.immediateFuture(queryResult);
    } catch (Exception e) {
        return Futures.immediateFailedFuture(e);
    }
}

การใช้โครูทีน

future{ ... } ใน Kotlin สามารถใช้เพื่อแปลงผลลัพธ์ของฟังก์ชันระงับเป็น ListenableFuture

import kotlinx.coroutines.guava.future

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

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

การแปลง Callback

หากต้องการแปลง API ที่อิงตาม Callback เป็น API ที่ใช้ ListenableFuture ให้ใช้ CallbackToFutureAdapter API นี้ให้บริการโดยอาร์ติแฟกต์ androidx.concurrent:concurrent-futures

ดูข้อมูลเพิ่มเติมได้ที่ androidx.concurrent

กำลังแปลงจาก RxJava Single

เมื่อใช้ RxJava Single สามารถแปลงเป็น SettableFuture ได้ ซึ่งใช้ ListenableFuture

KotlinJava
fun getResult(): ListenableFuture<QueryResult> {
    val single: Single<QueryResult> = ...

    val future = SettableFuture.create<QueryResult>()
    single.subscribe(future::set, future::setException)
    return future
}
public ListenableFuture<QueryResult> getResult() {
    Single<QueryResult> single = ...

    SettableFuture<QueryResult> future = SettableFuture.create();
    single.subscribe(future::set, future::setException);
    return future;
}