استخدام ListenableFuture

تمثّل السمة ListenableFuture نتيجة عملية حسابية غير متزامنة، وهي عملية حاسوبية قد تكون انتهت أو لم تنتهِ عملية الحصول على النتيجة بعد. هي عبارة عن نوع من Future يسمح لك بتسجيل طلبات استدعاء لتنفيذها فور اكتمال العملية الحسابية أو إذا كانت العملية قد اكتملت على الفور.

ListenableFuture ليس جزءًا من إطار عمل Android ويتم توفيره بدلاً من ذلك بواسطة Guava. لمزيد من المعلومات حول استخدام هذا الصف، يُرجى الاطّلاع على مقالة ListenableFuture توضيحية.

تتضمّن العديد من مكتبات Jetpack الحالية، مثل cameraX أو Health Services، طرقًا غير متزامنة يكون فيها نوع العرض ListenableFuture الذي يمثّل حالة التنفيذ. في بعض الحالات، قد تحتاج إلى تنفيذ طريقة تعرض ListenableFuture، مثلاً لاستيفاء متطلبات TileService.

المكتبات المطلوبة

رائع

dependencies {
    implementation "com.google.guava:guava:31.0.1-android"

    // To use CallbackToFutureAdapter
    implementation "androidx.concurrent:concurrent-futures:1.1.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.1.0")

    // Kotlin
    implementation("org.jetbrains.kotlinx:kotlinx-coroutines-guava:1.6.0")
}

الحصول على نتيجة ListenableFuture

إضافة معاودة الاتصال

يمكنك استخدام طريقة المساعدة Futures.addCallback(...) لإرفاق استدعاءات النجاح والفشل في 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()
);

جارٍ التعليق في Kotlin

عند استخدام لغة Kotlin، فإنّ أسهل طريقة لانتظار نتيجة LookerableFuture هي استخدام await().

import kotlinx.coroutines.guava.await

...

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

إمكانية التشغيل التفاعلي مع RxJava

يمكن إنشاء RxJava Single من ListenableFuture عن طريق تسجيل عمليات معاودة الاتصال داخل 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));

جارٍ إنشاء ListenableFuture

إنشاء مستقبل مباشر

إذا لم تكن واجهة برمجة التطبيقات غير متزامنة، ولكنك تحتاج إلى دمج نتيجة العملية المكتملة في ListenableFuture، يمكنك إنشاء ImmediateFuture. يمكن إجراء ذلك باستخدام طريقة عمل 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);
    }
}

استخدام الكوروتين

في Kotlin، يمكن استخدام future{ ... } لتحويل نتيجة دالة التعليق إلى ListenableFuture.

import kotlinx.coroutines.guava.future

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

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

تحويل مكالمة معاودة الاتصال

لتحويل واجهة برمجة تطبيقات مستندة إلى معاودة الاتصال إلى واجهة برمجة تطبيقات تستخدم ListenableFuture، يمكنك استخدام CallbackToFutureAdapter. يتم توفير واجهة برمجة التطبيقات هذه من خلال عنصر androidx.concurrent:concurrent-futures.

يمكنك الاطّلاع على androidx.concurrent للحصول على مزيد من المعلومات.

جارٍ التحويل من RxJava Single

عند استخدام RxJava، يمكن تحويل Single إلى SettableFuture، والتي تنفذ 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;
}