web-dev-qa-db-fra.com

Existe-t-il un moyen d’utiliser les interfaces fonctionnelles Java 8 sur l’API Android en dessous de 24?

Je peux utiliser retrolambda pour activer les lambdas avec un niveau d'API Android <24. Donc ça marche

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

Cela fonctionne aussi

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

Mais celui-ci ne

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

Le dernier fonctionne sur l'API Android de niveau 24, mais sur d'autres appareils, ce code provoque un crash

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

Au lieu d'utiliser retrolambda, j'ai essayé d'activer Java 8. Les deux premiers exemples de code fonctionnent toujours, bien que butterknife ait cessé de fonctionner. https://developer.Android.com/preview/j8-jack.html#configuration here ava.util.function est censé être pris en charge, mais j'obtiens toujours un blocage lors de l'exécution du troisième, cette fois-ci un peu différent

Java.lang.NoClassDefFoundError: com.retrolambdatry.MainActivity$-void_onCreate_Android_os_Bundle_savedInstanceState_LambdaImpl1
17
sasha199568

Vous n'êtes pas sûr d'avoir encore besoin d'une réponse à cette question, mais d'autres (comme moi) pourraient le faire.

En tant que version 3.0, Android Studio prend en charge de manière native les fonctions lambda et de nombreuses autres fonctions Java 8 à tous les niveaux d'API, mais certaines (comme les interfaces fonctionnelles et Java.util.function) sont toujours limitées aux API 24+.

Jusqu'à ce que ce support soit étendu, Android-retrostreams fournit un support de backport pour la plupart. Ce projet est un "port mis à niveau" de la bibliothèque streamsupport , que vous pouvez également utiliser, et possède de nombreuses fonctionnalités dans les flux rétros par Android. La bibliothèque streamsupport prend en charge jusqu'à Java 6/7, vous pouvez donc l'utiliser même si vous ne possédez pas AS 3.0+ ou si vous ne ciblez pas Java 8, mais vous ferez probablement mieux d'utiliser Android-retrostreams dans la plupart des cas, si vous pouvez. Vous pouvez consulter les javadocs du projet pour voir exactement ce qui est proposé, mais les points forts que j'ai utilisés sont Java.util.function et Java.util.Comparator.

Notez que Java dans les noms de package est remplacé par Java9 et que certains noms de classe et/ou de méthode ont peut-être été légèrement modifiés. Par exemple:

Java.util.function devient Java9.util.function,

tandis que

Java.util.Comparator devient Java9.util.Comparators (et avec des noms de méthode et des modèles d'appel légèrement différents, mais avec la même fonctionnalité).

14
VerumCH

La bibliothèque de support Android (AndroidX) a maintenant Consumer et Supplier:

malheureusement seules ces deux interfaces sont ajoutées au moment de l'écriture. 

Maintenant, nous avons Kotlin, il n’est pas nécessaire de spécifier explicitement l’interface fonctionnelle:

    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
lazybug

Pour une alternative, Lightweight-Stream-API fournit également un support backport. Comme Android-retrostreams metION ci-dessus, vous devez remplacer certains noms de paquets en utilisant:

com.annimon.stream.function au lieu de Java.util.function

com.annimon.stream.ComparatorCompat au lieu de Java.util.Comparator

1
Shen Andrew