Android-Entwicklung mit Groovy

Know-how  –  3 Kommentare

Android-Entwicklung muss nicht immer gleichbedeutend mit Java-Programmierung sein. Spätestens seit Android Gradle als offizielles Build-System nutzt, rückt Groovy zunehmend ins Blickfeld der App-Entwickler.

Nachdem Apple Swift als alternative Sprache für iOS-Apps eingeführt hat, denkt so mancher darüber nach, ob es für Android etwas Ähnliches gibt. Zumal Entwicklern hier nur Java 6 beziehungsweise 7 ab Android Release 5.0 (Lollipop) zur Verfügung stehen. Bei Betrachtung der Swift-Syntax lassen sich schnell Ähnlichkeiten zu Groovy entdecken. Ein intensiver Blick auf die Sprache könnte also lohnen.

Im August 2014 verkündete die New York Times, die Sprache Groovy zur Entwicklung ihrer neuen Android-App einzusetzen. Die Programmierer suchten Wege, App-Code wiederverwendbarer und leichter an neue Features und APIs anpassbar zu machen. Mit Blick auf die mit Java 8 eingeführten Lambdas und der damit einhergehenden Möglichkeit funktionaler Entwicklungsparadigmen sowie der ausdrucksstarken Syntax fiel die Wahl auf Groovy.

Die Sprache ist objektorientiert wie Java, allerdings ermöglicht sie Mehrfachvererbung in Form von Traits. Gleichzeitig ist Groovy eine funktionale Programmiersprache, sodass sich Closures und Methodenreferenzen nutzen lassen. Im Gegensatz zu Java ist sie zudem dynamisch mit Features wie optionaler Typisierung, Coercion (erzwungene Typumwandlung) und Duck Typing.

In Groovy geschriebene Klassen entsprechen auf Bytecode-Ebene Java-Klassen, und die Verwendung der jeweils anderen ist transparent und ohne Konvertierung möglich. Deshalb ist man nicht gezwungen, die gesamte App in Groovy zu schreiben – bestehender Code und Bibiotheken lassen sich wie gewohnt verwenden.

Groovy bringt viele nützliche Features mit. Die für die Android-App-Entwicklung wichtigsten sollen im Folgenden vorgstellt werden.

Groovy ermöglicht den Einsatz aller Features aus Project Coin – auch bei Verwendung von Java 6. Hierunter fallen zum Beispiel switch-Statements mit Strings, binäre Literale oder Multi-Catch-Blöcke bei Exceptions. Was Java 8 angeht, so unterstützt Groovy derzeit keine versionsspezifischen Syntaxerweiterungen, allerdings ist die Syntax von Lambdas und Closures so ähnlich, dass Entwickler sie im Falle eines Umstiegs leicht oder gar automatisiert konvertieren können. Zudem lassen sich Closures beim Aufruf von Methoden automatisch in Lambdas umwandeln und können auf dieselbe Weise mit Java 8 verwendet werden.

Closures sind in erster Linie Codeblöcke und werden wie sie mit geschweiften Klammern ({}) notiert. Sie entsprechen zudem klassenlosen Methoden wie Lambdas, lassen sich Variablen zuweisen und können Argumente erhalten. Letztere werden anders als bei Java-8-Lambdas innerhalb der Klammern notiert und durch einen Pfeil (->) getrennt. Auch in Closure-Signaturen sind Datentypen optional.

def printName = { String vorname, nachname ->
System.out.println("$vorname $nachname")
}

Wenn eine Closure keine Argumente definiert, lässt sie sich mit oder ohne Argument aufrufen. Das Default-Argument bekommt den Namen it.

def printIt = {
println(it) // System.out kann weggelassen werden weil
//java.Object in Groovy die Methode `.println`
//implementiert.
}
printIt('Alexander') // Ausgabe: Alexander
printIt() // Ausgabe: null

Closures in Groovy sind Objekte vom Typ groovy.lang.Closure und haben Methoden, – etwa um sie aufzurufen:

printName.call('Alexander', 'Klein')  

Sie lassen sich aber auch wie Lambdas nur mit Klammern nutzen:

printName('Alexander', 'Klein')

Argumente können Default-Werte erhalten, die zum Einsatz kommen, falls das Argument beim Aufruf weggelassen wird.

Closure person = { name, wohnort = 'Unbekannt' ->
println "$name: $wohnort"
}
person('Alexander') // Ausgabe: Alexander Klein: Unbekannt

Wenn das erste Argument eine Map ist, lassen sich Argumente benennen, die im Anschluss als Key-Value-Paare in der Map landen.

Closure person = { Map params, name ->
println "$name: $params"
}
person('Alexander', wohnort: 'Stuttgart') // Ausgabe: Alexander:
// [wohnort:Stuttgart]

Wenn das letzte Argument eine Closure ist, können Entwickler sie beim Aufruf außerhalb der Argumentliste notieren.

Closure forEach(List list, Closure action) {
for(def element: list) {
action(element)
}
}
forEach([1,2,3]) { println it } // [1,2] ist ein Literal für eine List

Default-Werte, benannte Argumente und Closure-Parameter gelten in Groovy auch für normale Methoden.