استفاده از ListenableFuture

ListenableFuture نتیجه یک محاسبات ناهمزمان را نشان می دهد: محاسباتی که ممکن است هنوز تولید نتیجه را به پایان نرسانده باشد یا نکند. این یک نوع Future است که به شما امکان می‌دهد پس از اتمام محاسبات، یا اگر محاسبات از قبل کامل شده است، تماس‌های برگشتی را ثبت کنید تا اجرا شوند.

ListenableFuture بخشی از چارچوب Android نیست و در عوض توسط Guava ارائه شده است. برای اطلاعات بیشتر در مورد اجرای این کلاس، به توضیح ListenableFuture مراجعه کنید.

بسیاری از کتابخانه‌های Jetpack موجود مانند CameraX یا Health Services دارای روش‌های ناهمزمان هستند که نوع بازگشتی آن ListenableFuture است که وضعیت اجرا را نشان می‌دهد. در برخی موارد ممکن است نیاز به پیاده‌سازی روشی داشته باشید که یک ListenableFuture را برمی‌گرداند، مانند برآوردن الزامات TileService .

کتابخانه های مورد نیاز

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

گرفتن نتیجه از ListenableFuture

افزودن پاسخ به تماس

از روش کمکی Futures.addCallback(...) برای پیوست کردن تماس های موفقیت و شکست به ListenableFuture استفاده کنید.

کاتلین

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، ساده ترین راه برای منتظر ماندن برای نتیجه ListenableFuture استفاده از await() است.

import kotlinx.coroutines.guava.await

...

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

با RxJava تعامل داشته باشید

یک RxJava Single می توان از ListenableFuture با ثبت تماس های برگشتی در یک SingleEmitter ایجاد کرد.

کاتلین

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(...) انجام داد.

کاتلین

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

استفاده از کوروتین

در Kotlin، یک future{ ... } می تواند برای تبدیل نتیجه یک تابع تعلیق به ListenableFuture استفاده شود.

import kotlinx.coroutines.guava.future

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

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

تبدیل تماس برگشتی

برای تبدیل یک API مبتنی بر تماس به API که از ListenableFuture استفاده می کند، از CallbackToFutureAdapter استفاده کنید. این API توسط مصنوع androidx.concurrent:concurrent-futures ارائه شده است.

برای اطلاعات بیشتر به androidx.concurrent مراجعه کنید.

تبدیل از RxJava Single

هنگام استفاده از RxJava، یک Single می توان به SettableFuture تبدیل کرد که ListenableFuture پیاده سازی می کند.

کاتلین

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