Android NDK开发详解后台任务之使用 ListenableFuture

使用 ListenableFuture
ListenableFuture 表示异步计算的结果,即可能尚未生成结果的计算。它是一种 Future,用于注册要在计算完成后或计算完成后立即执行的回调。

ListenableFuture 不是 Android 框架的一部分,由 Guava 提供。如需详细了解此类的实现,请参阅 ListenableFuture 的说明。

许多现有的 Jetpack 库(如 CameraX 或健康服务)都具有异步方法,其中返回类型为表示执行状态的 ListenableFuture。在某些情况下,例如为了满足 TileService 的要求,您可能需要实现会返回 ListenableFuture 的方法。

提示:检查您使用的 Jetpack 库是否有 -ktx 工件,因为这些工件通常包含基于 ListenableFuture 的方法的内置封装容器。例如,androidx.work:work-runtime-ktx 将 WorkManager API 的封装容器作为挂起函数提供。

必需的库

Groovy

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 时,等待 ListenableFuture 结果的最简单方法是使用 await()。

import kotlinx.coroutines.guava.await

...

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

与 RxJava 互操作

您可以通过在 SingleEmitter 内注册回调,从 ListenableFuture 创建 RxJava Single。

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

为未来造势

如果您的 API 不是异步的,但您需要将已完成操作的结果封装到 ListenableFuture 中,则可以创建 ImmediateFuture。这可以使用 Futures.immediateFuture(…) 工厂方法完成。

警告 :仅建议立即获得结果时,才建议此示例代码。不应在同步 API 中使用 ImmediateFuture,例如当 getQueryResult() 是长时间运行的阻塞调用时。
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()
    }
}

转换回调

如需将基于回调的 API 转换为使用 ListenableFuture 的 API,请使用 CallbackToFutureAdapter。此 API 由 androidx.concurrent:concurrent-futures 工件提供。

如需了解详情,请参阅 androidx.concurrent。

从 RxJava Single 转换

使用 RxJava 时,可将 Single 转换为实现 ListenableFuture 的 SettableFuture。

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

本页面上的内容和代码示例受内容许可部分所述许可的限制。Java 和 OpenJDK 是 Oracle 和/或其关联公司的注册商标。

最后更新时间 (UTC):2023-11-03。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

五一编程

程序之路有我与你同行

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值