有没有办法在24以下的Android API上使用Java 8功能接口?

时间:2016-07-27 08:00:31

标签: java android lambda functional-interface retrolambda

我可以使用retrolambda来启用Android API级别<24的lambdas。 所以这个工作

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

这也有效

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

但这个不是

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

最后一个适用于Android API Level 24,但在其他设备上,此代码会导致崩溃

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

我试图启用Java 8.而不是使用retrolambda。前两个代码示例仍然有效,尽管butterknife停止工作。据说https://developer.android.com/preview/j8-jack.html#configuration ava.util.function支持java.lang.NoClassDefFoundError: com.retrolambdatry.MainActivity$-void_onCreate_android_os_Bundle_savedInstanceState_LambdaImpl1 ,但在运行第三个时我仍然会崩溃,这次是有点不同

navigation controller

5 个答案:

答案 0 :(得分:14)

不确定你是否还需要这个问题的答案,但其他人(比如我自己)可能。

作为版本3.0,Android Studio natively supports lambda functions以及所有API级别上的许多其他Java 8函数,但有些(如功能接口和java.util.function)仍限于API 24 +。

在扩展支持之前,android-retrostreams为大多数支持提供了后端支持。这个项目是一个升级的港口&#39; streamsupport library,你也可以使用,并具有android-retrostreams中的许多功能。 streamsupport库支持Java 6/7,所以即使你没有AS 3.0+或者没有针对Java 8,你也可以使用它,但你可能最好使用android-如果可以的话,在大多数情况下都会出现逆流。您可以浏览项目的javadoc以确切了解所提供的内容,但我使用的重点是java.util.functionjava.util.Comparator

请注意,程序包名称中的java将替换为java9,并且某些类和/或方法名称可能稍有更改。例如:

java.util.function变为java9.util.function

,而

java.util.Comparator变为java9.util.Comparators(并且方法名称和调用模式略有不同 - 但功能相同)。

答案 1 :(得分:2)

Android支持库(AndroidX)现在具有ConsumerSupplier

撰写时

only these two interfaces gets added很遗憾。

现在我们有了Kotlin,它不需要您显式指定功能接口:

    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()
    }

答案 2 :(得分:2)

Android Gradle 插件 (AGP) 4.0+ 在低 API 版本上添加对 java8 包(例如 java.util.function,已添加到 Android API 24)的向后移植支持:

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

将下面的代码行添加到 APP 模块允许我使用 openAPI-generator 5.1.0 生成的 java jersey API-SDK 模块和 Android API < 24(我使用 jersey 以获得更好的多态性支持)

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

答案 3 :(得分:1)

另外,Lightweight-Stream-API也提供后端支持。与上面提到的android-retrostreams一样,您必须使用以下内容替换某些包名:

com.annimon.stream.function代替java.util.function

com.annimon.stream.ComparatorCompat代替java.util.Comparator

答案 4 :(得分:-3)

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

代码:ipcjs/java-support