ListenableFuture
는 비동기 계산의 결과를 나타냅니다. 비동기 계산은 아직 결과 생성을 완료했을 수도 있고 완료하지 않았을 수도 있습니다. 이는 Future
의 한 유형으로, 계산이 완료되거나 계산이 이미 완료된 경우 즉시 실행될 콜백을 등록할 수 있습니다.
ListenableFuture
는 Android 프레임워크의 일부가 아니며 Guava에서 제공됩니다. 이 클래스의 구현에 관한 자세한 내용은 ListenableFuture 설명을 참고하세요.
CameraX 또는 건강 관리 서비스와 같은 많은 기존 Jetpack 라이브러리에는 반환 유형이 실행 상태를 나타내는 ListenableFuture
인 비동기 메서드가 있습니다. 경우에 따라 TileService
의 요구사항을 충족하기 위해 ListenableFuture
를 반환하는 메서드를 구현해야 할 수도 있습니다.
필수 라이브러리
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
에 연결합니다.
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와의 상호 운용성
RxJava Single
는 SingleEmitter
내에 콜백을 등록하여 ListenableFuture
에서 생성할 수 있습니다.
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(...)
팩토리 메서드를 사용하여 실행할 수 있습니다.
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; }