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).

Tags:

Android

Java 8