sasha199568
sasha199568

Reputation: 1153

Is there a way to use Java 8 functional interfaces on Android API below 24?

I can use retrolambda to enable lambdas with Android API level <24. So this works

myButton.setOnClickListener(view -> Timber.d("Lambdas work!"));

This also works

Runnable runLater = () -> Timber.d("Lambdas work!");
runLater.run();

But this one does not

Consumer<Integer> runLaterWithInt = (Integer i) -> Timber.d("i = " + i);
runLaterWithInt.accept(3);

The last one works on Android API Level 24, but on other devices this code causes a crash

java.lang.NoClassDefFoundError: com.retrolambdatry.MainActivity$$Lambda$1

Instead of using retrolambda I tried to enable Java 8. First two code examples still work, although butterknife stopped working. https://developer.android.com/preview/j8-jack.html#configuration here ava.util.function is said to be supported, but I still get a crash when running the third one, this time it is a little different

java.lang.NoClassDefFoundError: com.retrolambdatry.MainActivity$-void_onCreate_android_os_Bundle_savedInstanceState_LambdaImpl1

Upvotes: 32

Views: 12125

Answers (6)

Ahmet B.
Ahmet B.

Reputation: 1674

Use

import androidx.core.util.Consumer;

instead of

import java.util.function.Consumer; (requires min API 24)

Sample implementation

public static void sampleMethod(Consumer<Boolean> isClicked) {
    isClicked.accept(true);
}

usage of sample implementation

Utils.sampleMethod(new Consumer<Boolean>() {
        @Override
        public void accept(Boolean isClicked) {

        }
    });

Upvotes: 1

Vlad Bellegar
Vlad Bellegar

Reputation: 61

Android Gradle plugin (AGP) 4.0+ add backported support for java8 packages (such as java.util.function, which added to Android API 24) on low API version:

see https://developer.android.com/studio/write/java8-support#library-desugaring

Adding lines from code below to APP module allows me to use openAPI-generator 5.1.0 produced java jersey API-SDK module with Android API < 24 (I use jersey for better polymorphism support)

android {
  defaultConfig {
    // Required when setting minSdkVersion to 20 or lower
    multiDexEnabled true
  }

  compileOptions {
    // Flag to enable support for the new language APIs
    coreLibraryDesugaringEnabled true
    // Sets Java compatibility to Java 8
    sourceCompatibility JavaVersion.VERSION_1_8
    targetCompatibility JavaVersion.VERSION_1_8
  }
}

dependencies {
  coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.1.5'
}

Upvotes: 3

don&#39;t panic
don&#39;t panic

Reputation: 6133

Android support library(AndroidX) now has Consumer and Supplier:

sadly only these two interfaces gets added as of writing.

Now we have Kotlin, it doesn't require you to specify the functional interface explicitly:

    fun test() {
        val text = withPrintStream {
            it.println("Header bla bla ")
            it.printf("%s, %s, %s,", "a", "b", "c").println()
        }
    }

    // Equivalent to the following code in Java:
    //     Consumer<PrintStream> action;
    //     action.accept(ps);
    fun withPrintStream(action: (PrintStream) -> Unit): String {
        val byteArrayOutputStream = ByteArrayOutputStream()
        val ps = PrintStream(byteArrayOutputStream)
        action(ps)
        ps.flush()
        return byteArrayOutputStream.toString()
    }

Upvotes: 13

Shen Andrew
Shen Andrew

Reputation: 21

For alternative, Lightweight-Stream-API also provides backport support. Like android-retrostreams metioned above, you have to replace some package names by using:

com.annimon.stream.function instead of java.util.function

com.annimon.stream.ComparatorCompat instead of java.util.Comparator

Upvotes: 2

VerumCH
VerumCH

Reputation: 3175

Not sure if you still need an answer to this question, but others (like myself) might.

As version 3.0, Android Studio natively supports lambda functions and many other Java 8 functions on all API levels, but some (like Functional Interfaces and java.util.function) are still restricted to APIs 24+.

Until that support is expanded, android-retrostreams provides backport support for most of it. This project is an 'upgraded port' of the streamsupport library, which you can also use and has many of the functionalities in android-retrostreams. The streamsupport library supports down to Java 6/7, so you can use it even if you don't have AS 3.0+ or aren't targeting Java 8, but you're probably better off using android-retrostreams in most cases, if you can. You can go through the project's javadocs to see exactly what's offered, but highlights that I've used are java.util.function and java.util.Comparator.

Note that java in the package names is replaced with java9, and some of the class and/or method names may have been changed slightly. For example:

java.util.function becomes java9.util.function,

while

java.util.Comparator becomes java9.util.Comparators (and with slightly different method names and call patterns - but the same functionality).

Upvotes: 27

ipcjs
ipcjs

Reputation: 2249

allprojects {
    repositories {
        maven { url 'https://jitpack.io' }
    }
}
dependencies {
        compile 'com.github.ipcjs:java-support:0.0.3'
}

code: ipcjs/java-support

Upvotes: -1

Related Questions