CompletableFuture in the Android Support Library?
If you don't need all features of the CompletableFuture
(e.g. result chaining), you can use this class (Kotlin):
/**
* A backport of Java `CompletableFuture` which works with old Androids.
*/
class CompletableFutureCompat<V> : Future<V> {
private sealed class Result<out V> {
abstract val value: V
class Ok<V>(override val value: V) : Result<V>()
class Error(val e: Throwable) : Result<Nothing>() {
override val value: Nothing
get() = throw e
}
object Cancel : Result<Nothing>() {
override val value: Nothing
get() = throw CancellationException()
}
}
/**
* Offers the completion result for [result].
*
* If this queue is not empty, the future is completed.
*/
private val completion = LinkedBlockingQueue<Result<V>>(1)
/**
* Holds the result of the computation. Takes the item from [completion] upon running and provides it as a result.
*/
private val result = FutureTask<V> { completion.peek()!!.value }
/**
* If not already completed, causes invocations of [get]
* and related methods to throw the given exception.
*
* @param ex the exception
* @return `true` if this invocation caused this CompletableFuture
* to transition to a completed state, else `false`
*/
fun completeExceptionally(ex: Throwable): Boolean {
val offered = completion.offer(Result.Error(ex))
if (offered) {
result.run()
}
return offered
}
/**
* If not already completed, completes this CompletableFuture with
* a [CancellationException].
*
* @param mayInterruptIfRunning this value has no effect in this
* implementation because interrupts are not used to control
* processing.
*
* @return `true` if this task is now cancelled
*/
override fun cancel(mayInterruptIfRunning: Boolean): Boolean {
val offered = completion.offer(Result.Cancel)
if (offered) {
result.cancel(mayInterruptIfRunning)
}
return offered
}
/**
* If not already completed, sets the value returned by [get] and related methods to the given value.
*
* @param value the result value
* @return `true` if this invocation caused this CompletableFuture
* to transition to a completed state, else `false`
*/
fun complete(value: V): Boolean {
val offered = completion.offer(Result.Ok(value))
if (offered) {
result.run()
}
return offered
}
override fun isDone(): Boolean = completion.isNotEmpty()
override fun get(): V = result.get()
override fun get(timeout: Long, unit: TimeUnit): V = result.get(timeout, unit)
override fun isCancelled(): Boolean = completion.peek() == Result.Cancel
}
streamsupport
library mentioned in Stefan Zobel's answer was forked especially for Android Studio >=3.0 desugar toolchain, please check android-retrofuture
The streamsupport project provides a backport of CompletableFuture
in its streamsupport-cfuture
component which can be used for Android development, supported on all devices.
Either use
dependencies {
implementation 'net.sourceforge.streamsupport:streamsupport-cfuture:1.7.4'
}
or the more modern android-retrofuture fork for Android Studio >= 3.x
dependencies {
implementation 'net.sourceforge.streamsupport:android-retrofuture:1.7.4'
}
if you can use Android Studio 3.x and above.
The new Java 12 exception handling methods for CompletableFuture JDK-8211010 have been integrated in release 1.7.0
For users who want a minimal dependency footprint there is also a 105 KiB minifuture
variant which is a "stripped to the bones" version of streamsupport-cfuture
.
dependencies {
implementation 'net.sourceforge.streamsupport:streamsupport-minifuture:1.7.4'
}
This has no dependencies and provides only the minimum API necessary to use CompletableFuture
and nothing else (no Streams, no public ForkJoinPool and such).